From a5a19fd672bc0b8113d620669b557f17dccd343a Mon Sep 17 00:00:00 2001 From: Christian Schneider Date: Thu, 26 Oct 2006 13:35:12 +0000 Subject: Moved itools to live branch --- .diffnotice | 6 + .gitattributes | 2 + .gitignore | 11 + .notice | 0 Makefile | 68 +++++++ banner.lib | 3 + banner/.cvsignore | 2 + banner/Makefile | 48 +++++ banner/banner.class | 289 +++++++++++++++++++++++++++ browser.class | 126 ++++++++++++ config.class | 36 ++++ darwin/.cvsignore | 2 + darwin/Makefile | 47 +++++ darwin/query.class | 95 +++++++++ db.class | 250 +++++++++++++++++++++++ db_record.class | 520 ++++++++++++++++++++++++++++++++++++++++++++++++ db_table.class | 425 +++++++++++++++++++++++++++++++++++++++ dbi.class | 450 +++++++++++++++++++++++++++++++++++++++++ debug.class | 180 +++++++++++++++++ fax.class | 127 ++++++++++++ html.class | 516 +++++++++++++++++++++++++++++++++++++++++++++++ html_form.class | 166 ++++++++++++++++ html_page.class | 214 ++++++++++++++++++++ it.class | 133 +++++++++++++ itjs.class | 131 ++++++++++++ itjs.php | 57 ++++++ itjs/boot.js | 136 +++++++++++++ itjs/error.gif | Bin 0 -> 43 bytes itjs/it.js | 165 +++++++++++++++ itjs/loader.js | 207 +++++++++++++++++++ itjs/state.html | 29 +++ itjs/state.js | 114 +++++++++++ itjs/timer.js | 64 ++++++ itools.lib | 22 ++ license/.cvsignore | 1 + license/Makefile | 47 +++++ license/license.class | 142 +++++++++++++ mail.class | 480 ++++++++++++++++++++++++++++++++++++++++++++ session.class | 231 +++++++++++++++++++++ sms.lib | 3 + sms/Makefile | 47 +++++ sms/sms.class | 122 ++++++++++++ support.pinc | 226 +++++++++++++++++++++ text.class | 422 +++++++++++++++++++++++++++++++++++++++ time.pinc | 139 +++++++++++++ url.class | 484 ++++++++++++++++++++++++++++++++++++++++++++ urlcache/.cvsignore | 2 + urlcache/Makefile | 48 +++++ urlcache/urlcache.class | 225 +++++++++++++++++++++ urlcache/urlcache.php | 28 +++ urlcache/urlcache.sql | 14 ++ user.class | 511 +++++++++++++++++++++++++++++++++++++++++++++++ xml.class | 269 +++++++++++++++++++++++++ 53 files changed, 8082 insertions(+) create mode 100644 .diffnotice create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .notice create mode 100644 Makefile create mode 100644 banner.lib create mode 100644 banner/.cvsignore create mode 100644 banner/Makefile create mode 100644 banner/banner.class create mode 100644 browser.class create mode 100644 config.class create mode 100644 darwin/.cvsignore create mode 100644 darwin/Makefile create mode 100644 darwin/query.class create mode 100644 db.class create mode 100644 db_record.class create mode 100644 db_table.class create mode 100644 dbi.class create mode 100644 debug.class create mode 100644 fax.class create mode 100644 html.class create mode 100644 html_form.class create mode 100644 html_page.class create mode 100644 it.class create mode 100644 itjs.class create mode 100644 itjs.php create mode 100644 itjs/boot.js create mode 100644 itjs/error.gif create mode 100644 itjs/it.js create mode 100644 itjs/loader.js create mode 100644 itjs/state.html create mode 100644 itjs/state.js create mode 100644 itjs/timer.js create mode 100644 itools.lib create mode 100644 license/.cvsignore create mode 100644 license/Makefile create mode 100644 license/license.class create mode 100644 mail.class create mode 100644 session.class create mode 100644 sms.lib create mode 100644 sms/Makefile create mode 100644 sms/sms.class create mode 100644 support.pinc create mode 100644 text.class create mode 100644 time.pinc create mode 100644 url.class create mode 100644 urlcache/.cvsignore create mode 100644 urlcache/Makefile create mode 100644 urlcache/urlcache.class create mode 100644 urlcache/urlcache.php create mode 100644 urlcache/urlcache.sql create mode 100644 user.class create mode 100644 xml.class diff --git a/.diffnotice b/.diffnotice new file mode 100644 index 0000000..41bcacd --- /dev/null +++ b/.diffnotice @@ -0,0 +1,6 @@ +schneider@search.ch +weber@search.ch +demesmaeker@search.ch +koni@search.ch +seefeld@search.ch +mueller@search.ch diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9c7115f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto !eol +itjs/error.gif -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..25c5961 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/*.lib +/*.slib +banner/*.lib +banner/*.slib +darwin/*.lib +darwin/*.slib +license/license.slib +sms/*.lib +sms/*.slib +urlcache/*.lib +urlcache/*.slib diff --git a/.notice b/.notice new file mode 100644 index 0000000..e69de29 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1bdb140 --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +## +## $Id$ +## +## Makefile for itools.lib +## +## Copyright (C) 1995-2003 by the ITools Authors. +## This program is free software; you can redistribute it and/or +## modify it under the terms of either the GNU General Public License +## or the GNU Lesser General Public License as published by the Free +## Software Foundation. +## + +CPP= cpp -traditional +QUIETMAKE= $(MAKE) -s +PHPCOMPILE= /usr/local/bin/phpcompile + +MODULE= itools +SUBDIRS= banner darwin license sms urlcache +CLASSES= support.pinc it.class browser.class db.class db_record.class db_table.class dbi.class debug.class html.class html_form.class html_page.class itjs.class mail.class fax.class session.class text.class url.class user.class xml.class + +# +# Library creation rules, do not change stuff below... +# +SLIB= $(MODULE).slib +LIB= $(MODULE)-compiled.lib +DEVEL= $(MODULE)-devel.lib + +all: + @echo Nothing to do. You may want to make $(MODULE)-compiled.lib + +all2: $(LIB) $(DEVEL) $(SUBDIRS) + +$(LIB): $(SLIB) Makefile + @if [ -x $(PHPCOMPILE) ]; then (echo Compiling $(SLIB) to $(LIB) ...) 1>&2; cat $(SLIB) license/license.slib | $(PHPCOMPILE) >$(LIB); else (echo $(PHPCOMPILE) not found, copying $(SLIB) to $(LIB) ...) 1>&2; cp $(SLIB) $(LIB); fi + +$(SLIB): $(CLASSES) DUMMY + @(echo Creating $(SLIB) from $(SUBDIRS) $(CLASSES) ...) 1>&2 + @echo -e "$(SLIB) + @(for class in DUMMY $(CLASSES); do test -f $$class && cat $$class; done) | $(CPP) -P -undef | perl -ne 's/^\s+//g; print unless /^\s*$$/' | grep -v "^" >>$(SLIB) + @echo "?>" >>$(SLIB) + +$(DEVEL): $(CLASSES) Makefile + @echo "$(DEVEL) + @(for class in $(CLASSES); do test -f $$class && echo "require_once('itools/$$class');"; done) >>$(DEVEL) + @echo "?>" >>$(DEVEL) + +## Rule to merge all of SLIB and SUBDIRS/SLIBS into one big SLIB +#$(SLIB): $(CLASSES) DUMMY +# @(echo Creating $(SLIB) from $(SUBDIRS) $(CLASSES) ...) 1>&2 +# @echo "$(SLIB) +# @(for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) cat); done; for class in DUMMY $(CLASSES); do test -f $$class && cat $$class; done) | $(CPP) -P -undef | perl -ne 's/^\s+//g; print unless /^\s*$$/' | grep -v "^" >>$(SLIB) +# @echo "?>" >>$(SLIB) + +$(SUBDIRS):: + @(cd $@; $(QUIETMAKE)) + +DUMMY: + +cat: $(SLIB) + @cat $(SLIB) + +clean: + @(echo Cleaning $(SLIB) $(LIB) ...) 1>&2 + @rm -f $(SLIB) $(LIB) $(DEVEL) + @for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) $@) || :; done + +delsource: + @rm -rf *.slib license.lib $(DEVEL) $(CLASSES) $(SUBDIRS) diff --git a/banner.lib b/banner.lib new file mode 100644 index 0000000..4de6252 --- /dev/null +++ b/banner.lib @@ -0,0 +1,3 @@ + diff --git a/banner/.cvsignore b/banner/.cvsignore new file mode 100644 index 0000000..b8e8856 --- /dev/null +++ b/banner/.cvsignore @@ -0,0 +1,2 @@ +*.slib +*.lib diff --git a/banner/Makefile b/banner/Makefile new file mode 100644 index 0000000..8e607aa --- /dev/null +++ b/banner/Makefile @@ -0,0 +1,48 @@ +## +## $Id$ +## +## Makefile for itools/banner.lib +## +## $Log$ +## Revision 1.1 2000/02/25 18:49:46 weber +## Hello, world! +## +## + +CPP= cpp +QUIETMAKE= $(MAKE) -s +PHPCOMPILE= /usr/local/bin/phpcompile + +MODULE= banner +SUBDIRS= +CLASSES= banner.class + +# +# Library creation rules, do not change stuff below... +# +SLIB= $(MODULE).slib +LIB= ../$(MODULE).lib + +all: $(LIB) + +$(LIB): $(SLIB) + @if [ -x $(PHPCOMPILE) ]; then (echo Compiling $(SLIB) to $(LIB) ...) 1>&2; $(PHPCOMPILE) <$(SLIB) >$(LIB); else (echo $(PHPCOMPILE) not found, copying $(SLIB) to $(LIB) ...) 1>&2; cp $(SLIB) $(LIB); fi + +$(SLIB): $(CLASSES) DUMMY + @(echo Creating $(SLIB) from $(SUBDIRS) $(CLASSES) ...) 1>&2 + @echo "$(SLIB) + @(for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) cat); done; for class in DUMMY $(CLASSES); do test -f $$class && cat $$class; done) | $(CPP) -P -undef | perl -ne 's/^\s+//g; print unless /^\s*$$/' | grep -v "^" >>$(SLIB) + @echo "?>" >>$(SLIB) + +$(SUBDIRS):: + @(cd $@; $(QUIETMAKE)) + +DUMMY: + +cat: $(SLIB) + @cat $(SLIB) + +clean: + @(echo Cleaning $(SLIB) $(LIB) ...) 1>&2 + @rm -f $(SLIB) $(LIB) + @for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) $@) || :; done diff --git a/banner/banner.class b/banner/banner.class new file mode 100644 index 0000000..214fcb7 --- /dev/null +++ b/banner/banner.class @@ -0,0 +1,289 @@ +p = (array)$p + array( + 'server' => "http://localhost/", + 'serverbase' => "http://localhost/getbanner.html", + 'host' => $_SERVER['HTTP_HOST'], + 'uri' => str_replace('/doc_static', '', $_SERVER['PHP_SELF']), + 'place' => "", + 'language' => "", + 'keyword' => "", + 'category' => "", + 'region' => "", + 'vars' => array(), + 'ip' => $_SERVER['REMOTE_ADDR'], + 'uid' => $_COOKIE['UID'], + 'bgcolor' => "", + 'width' => "", + 'height' => "", + 'mx1' => "", + 'mx2' => "", + 'my1' => "", + 'my2' => "", + 'z' => "", + 'target' => "_top", + 'timeout' => 5, + 'uidcookie' => 'crustulum', + 'enablephpbanners' => false, + 'addextraline' => "", + 'bannerid' => $_REQUEST["bannerid"], + 'exclude' => $_REQUEST["exclude"], + ); + + $this->p += array('loc' => $this->p['region']); # Historical name +} + +function choose() +{ + if ($GLOBALS['debug_noads']) + return; + + $host = 'localhost'; + $port = 80; + $url = '/'; + + if (eregi('^[a-z]+://([^:/]+):([0-9]+)(.*)', $this->p['serverbase'], $regs)) + { + $host = $regs[1]; + $port = $regs[2]; + $url = $regs[3]; + } + else if (eregi('^[a-z]+://([^:/]+)(.*)', $this->p['serverbase'], $regs)) + { + $host = $regs[1]; + $port = 80; + $url = $regs[2]; + } + + if ($url == '') + $url = '/'; + + $params = array(); + + foreach (array('host', 'uri', 'place', 'language', 'keyword', 'category', 'loc', 'mx1', 'mx2', 'my1', 'my2', 'z', 'ip', 'uid', 'bgcolor', 'bannerid', 'exclude') as $key) + $params[$key] = $this->p[$key]; + + $request .= it_html::U($url, $params); + if ($GLOBALS['debug_adreq']) # can't use EDC since itools sometimes not included + ED("http://$host$request"); + + if ($fp = @fsockopen($host, $port, $errno, $errstr, $this->p['timeout'])) + { + if ($this->p['uid']) + $cookie = "Cookie: " . $this->p['uidcookie'] . "=" . urlencode($this->p['uid']) . "\r\n"; + else + $cookie = ''; + + fputs($fp, "GET $request HTTP/1.0\r\nHost: $host\r\n$cookie\r\n"); + + $b = array(); + + while (!feof($fp)) + { + $line = fgets($fp, 10240); + + if (!trim($line)) + $emptylines++; + + if ($emptylines == 0) + ; + else if (ereg("^data (.*)$", $line, $r)) + { + $len = (int)$r[1]; + $b['data'] = ''; + + while (!feof($fp) && (strlen($b['data']) < $len)) + $b['data'] .= fread($fp, $len - strlen($b['data'])); + + if (strlen($b['data']) < $len) + $b['data'] = ''; # Skip banners which got corrupted during transmission, very rare + } + else if (ereg("^([^ ]*) (.*)\n$", $line, $r)) + { + $b[$r[1]] = $r[2]; + } + else if (ereg("^", $line)) + { + # Doubleclick artificially delays banners for Mozilla/Linux so we do not show them to linux users + if (!(eregi('linux', $_SERVER['HTTP_USER_AGENT']) && eregi('\.doubleclick\.net', $b['data']))) + { + $this->bannersbyposition[$b['position'] ? $b['position'] : 'banner'] = $b; + $this->banners[] = $b; + } + + $b = array(); + } + } + + if ($GLOBALS['debug_adreq']) # can't use EDC since itools sometimes not included + ED($this->banners); + } + + srand((double)microtime()*1000000); + $this->rand = rand(); +} + +/** + * Show one or all banners for this banner position + * @param $nocount Switch off impression counting of true for multiple display + * @param $noecho Switch off automatic display of HTML snipplet with echo + * @return HTML snipplet to insert banner(s) if $noecho is set, undefined otherwise + */ +function show($nocount = 0, $noecho = false) +{ + if (!is_array($this->banners)) + return; // none found or choose() not called yet + + $count = count($this->banners); + $number = 0; + + if ($noecho) + ob_start(); + + foreach ($this->banners as $banner) + { + $result .= $this->render($banner, $count, $number); + $number++; + } + + if ($noecho) + { + $result = ob_get_contents(); + ob_end_clean(); + } + + return $result; +} + +/** + * Returns html code for a banner from a multi banner request + * @param $position Which position to return, e.g. 'feature' + * @param $nocount Suppress counting of this banner + */ +function showcombined($position = "banner", $nocount = false) +{ + ob_start(); + if ($this->bannersbyposition[$position]) + $this->render($this->bannersbyposition[$position], 1, 0); + $result = ob_get_contents(); + ob_end_clean(); + + return $result; +} + +/** + * Renders a banner, to be overloaded e.g. to render sponsor banners in a table + * @param $banner Opaque structure representing the banner + * @param $count Total number of banners, also number of times this method gets called + * @param $position Current banner number, from 0 to $count - 1 + */ +function render($banner, $count, $number) +{ + if ($number > 0) + echo "

"; + + $this->render_banner($banner); +} + +/** + * Render one banner + * @param $banner Opaque banner structure to be rendered + */ +function render_banner($banner) +{ + if ($banner['width'] <= 0) + $banner['width'] = 468; + if ($banner['height'] <= 0) + $banner['height'] = 60; + if ($this->p['width']) + $banner['width'] = $this->p['width']; + if ($this->p['height']) + $banner['height'] = $this->p['height']; + $l = $banner['locationid']; + if (strlen($banner['matchingkeyword']) + strlen($banner['matchingcategory']) + strlen($banner['matchingregion']) + strlen($banner['language']) > 0) + $l .= "|" . $banner['matchingkeyword']; + if (strlen($banner['matchingcategory']) + strlen($banner['matchingregion']) + strlen($banner['language']) > 0) + $l .= "|" . $banner['matchingcategory']; + if (strlen($banner['matchingregion']) + strlen($banner['language']) > 0) + $l .= "|" . $banner['matchingregion']; + if (strlen($banner['language']) > 0) + $l .= "|" . $banner['language']; + $l = str_replace("/", "_", $l); + + $rand = $this->rand; + + $pathinfo = "/c=" . $banner['campaignid'] . ":" . urlencode($banner['campaignname']) . "/b=" . $banner['bannerid'] . ":" . urlencode($banner['bannername']) . "/l=" . urlencode($l); + $nocountinfo = $nocount ? "/nocount=1" : ""; + $viewpre = $this->p['server'] . "view.html$pathinfo$nocountinfo/img="; + $clickpre = $this->p['server'] . "click.html$pathinfo/url="; + $clickpreenc = urlencode($clickpre); + $auditurl = $viewpre . "empty.gif"; + + $keyword = $this->p['keyword']; + $keyword = preg_replace('/]*>/', '', $keyword); + $keyword = ereg_replace('\]\[', ' ', $keyword); + $keyword = ereg_replace('^\[ +', '', $keyword); + $keyword = ereg_replace(' +\]$', '', $keyword); + $keywordhtml = htmlentities(substr($keyword, 0, 30)); + $keywordurl = urlencode($keyword); + + extract($this->p['vars'], EXTR_SKIP); + + while (eregi("__([a-z]*)__", $banner['alttext'], $r)) + $banner['alttext'] = str_replace($r[0], ${strtolower($r[1])}, $banner['alttext']); + while (eregi("__([a-z]*)__", $banner['extraline'], $r)) + $banner['extraline'] = str_replace($r[0], ${strtolower($r[1])}, $banner['extraline']); + while (eregi("__([a-z]*)__", $banner['path'], $r)) + $banner['path'] = str_replace($r[0], ${strtolower($r[1])}, $banner['path']); + while (eregi("__([a-z]*)__", $banner['url'], $r)) + $banner['url'] = str_replace($r[0], ${strtolower($r[1])}, $banner['url']); + $viewurl = $viewpre . $banner['path']; + $clickurl = $clickpre . $banner['url']; + while (eregi("__([a-z]*)__", $banner['data'], $r)) + $banner['data'] = str_replace($r[0], ${strtolower($r[1])}, $banner['data']); + + switch ($banner['type']) + { + case 0: + if (eregi('&', $viewurl) && !eregi('&[a-z]+;', $viewurl)) + $viewurl = htmlspecialchars($viewurl); + + if (eregi('&', $clickurl) && !eregi('&[a-z]+;', $clickurl)) + $clickurl = htmlspecialchars($clickurl); + + if($banner['url'] != 'http://') + { + $linkstart = "p['target']) . "\">"; + $linkend = ""; + } + + echo "$linkstart\""$linkend"; + + if (strlen($banner['extraline']) > 0) + echo "
$linkstart" . $banner['extraline'] . $linkend; + + if (strlen($banner['extraline']) == 0 && $this->p['addextraline']) + echo "
 "; + break; + case 1: + echo $banner['data']; + break; + case 2: + if ($this->p['enablephpbanners']) + eval("?>" . $banner['data']); + break; + } +} + +} +?> diff --git a/browser.class b/browser.class new file mode 100644 index 0000000..2018247 --- /dev/null +++ b/browser.class @@ -0,0 +1,126 @@ +UserAgent = $_SERVER['HTTP_USER_AGENT']; + /* $this->UserAgent = "Mozilla/4.0 [de] (compatible; MSIE 5.0; Bill Gates 1.0; Windows 95)"; */ + + /* Find "Mozilla/4.0" */ + if (ereg("([^/]*)/([^ ]*)", $this->UserAgent, $regs)) + { + $this->Type = $regs[1]; + $this->Version = (double)$regs[2]; + } + + /* Find optional "(compatible; MSIE 3.0; Win95)" */ + if (ereg("\((.*)\)", $this->UserAgent, $regs)) + { + $optattr = split("; ", $regs[1]); + if ($optattr[0] == "compatible") + { + if (ereg("([^/]*)[/ ]([^/]*)", $optattr[1], $regs)) + { + $this->Type = $regs[1]; + $this->Version = (double)$regs[2]; + } + else $this->Type = $optattr[1]; + $this->Platform = $optattr[count($optattr)-1]; + } + else + $this->Platform = $optattr[0]; + } + + if ($this->Type == "Mozilla") + $this->Type = "Netscape"; + + /* Find optional "[de]" */ + if (ereg("\[(.*)\]", $this->UserAgent, $regs)) + $this->Language = $regs[1]; + + /* And now for the browser capabilities ... */ + if ($this->Type == "MSIE") + { + $this->MSIE = $this->Version; + $this->HTMLVersion = 4.0; + $this->JavaScript = 1; + + if ($this->Version >= 4.0) + $this->CSS = 2; + } + else if ($this->Type == "Opera") + { + $this->Opera = $this->Version; + if ($this->Version >= 3.5) + $this->HTMLVersion = 4.0; + else + $this->HTMLVersion = 3.2; + $this->JavaScript = 1; + } + else if ($this->Type == "Konqueror") + { + $this->HTMLVersion = 4.0; + $this->CSS = 2; + $this->JavaScript = 1; + } + else if ($this->Type == "Netscape") + { + $this->NS = $this->Version; + $this->HTMLVersion = 4.0; + $this->JavaScript = 1; + + if ($this->Version >= 5.0) + $this->CSS = 2; + } + else if ($this->Type == "Lynx") + $this->TextOnly = 1; +} + +} /* End Class it_Browser */ +?> diff --git a/config.class b/config.class new file mode 100644 index 0000000..0998c28 --- /dev/null +++ b/config.class @@ -0,0 +1,36 @@ +project_root = dirname($_SERVER['DOCUMENT_ROOT']); +} + +} /* End Class it_config */ + +?> diff --git a/darwin/.cvsignore b/darwin/.cvsignore new file mode 100644 index 0000000..b8e8856 --- /dev/null +++ b/darwin/.cvsignore @@ -0,0 +1,2 @@ +*.slib +*.lib diff --git a/darwin/Makefile b/darwin/Makefile new file mode 100644 index 0000000..d6c4aa1 --- /dev/null +++ b/darwin/Makefile @@ -0,0 +1,47 @@ +## +## $Id$ +## +## Makefile for itools/darwin.lib +## +## $Log$ +## Revision 1.1 2000/01/12 02:26:20 weber +## Added darwin query class +## + +CPP= cpp +QUIETMAKE= $(MAKE) -s +PHPCOMPILE= /usr/local/bin/phpcompile + +MODULE= darwin +SUBDIRS= +CLASSES= query.class + +# +# Library creation rules, do not change stuff below... +# +SLIB= $(MODULE).slib +LIB= ../$(MODULE).lib + +all: $(LIB) + +$(LIB): $(SLIB) + @if [ -x $(PHPCOMPILE) ]; then (echo Compiling $(SLIB) to $(LIB) ...) 1>&2; $(PHPCOMPILE) <$(SLIB) >$(LIB); else (echo $(PHPCOMPILE) not found, copying $(SLIB) to $(LIB) ...) 1>&2; cp $(SLIB) $(LIB); fi + +$(SLIB): $(CLASSES) DUMMY + @(echo Creating $(SLIB) from $(SUBDIRS) $(CLASSES) ...) 1>&2 + @echo "$(SLIB) + @(for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) cat); done; for class in DUMMY $(CLASSES); do test -f $$class && cat $$class; done) | $(CPP) -P -undef | perl -ne 's/^\s+//g; print unless /^\s*$$/' | grep -v "^" >>$(SLIB) + @echo "?>" >>$(SLIB) + +$(SUBDIRS):: + @(cd $@; $(QUIETMAKE)) + +DUMMY: + +cat: $(SLIB) + @cat $(SLIB) + +clean: + @(echo Cleaning $(SLIB) $(LIB) ...) 1>&2 + @rm -f $(SLIB) $(LIB) + @for dir in DUMMY $(SUBDIRS); do (test -d $$dir && cd $$dir && $(QUIETMAKE) $@) || :; done diff --git a/darwin/query.class b/darwin/query.class new file mode 100644 index 0000000..f0a5b7e --- /dev/null +++ b/darwin/query.class @@ -0,0 +1,95 @@ +service = $service; + $this->resultsperpage = $resultsperpage; + $this->totalresults = $this->firstresult = $this->lastresult = 0; + } + + + /* + ** Perform a query for $q starting at $rank. Return true on success, + ** false on error (no results is not an error) + */ + function query($q, $rank=0) + { + global $it_text; + + if (is_object($it_text)) + $lang = "&lang=" . $it_text->get_language(); + + $url = $this->service . "?q=" . urlencode($q) . "$lang&rank=$rank&n=" . $this->resultsperpage; + + /* debug("it_darwin::query(\"$url\",$rank)"); */ + + if ($this->result = file($url)) + { + $this->totalresults = trim($this->result[2]); + $this->firstresult = trim($this->result[3]); + $this->lastresult = trim($this->result[4]); + $this->resptr = $this->firstresult; + return 1; + } + return 0; + } + + /* Fetch a result as an array "url", "title", "description", "size", "date" */ + function fetch_array($number="XX") + { + /* debug("fetch_array($number), resptr==$this->resptr"); */ + if ($number != "XX") + $this->resptr = $number; + + if (($this->resptr >= $this->firstresult) && ($this->resptr <= $this->lastresult)) + { + $n = 5+($this->resptr-$this->firstresult)*5; /* start of result record */ + $this->resptr+=1; /* Spinn ich?? ++ geht nicht !! */ + return array("url" => trim($this->result[$n]), "title" => trim($this->result[$n+1]), "description" => trim($this->result[$n+2]), "size" => trim($this->result[$n+3])*1024, "date" => trim($this->result[$n+4])); + } + else return 0; /* Out of bounds */ + + } +} /* End class it_darwin_query */ +?> diff --git a/db.class b/db.class new file mode 100644 index 0000000..f94861a --- /dev/null +++ b/db.class @@ -0,0 +1,250 @@ +link = @mysql_connect($host, $username, $password, true)) + { + if (mysql_select_db($databasename, $this->link)) + { + $this->host = $host; + $this->name = $databasename; + } + else + internal_error("Can't select database \"$databasename\" on host \"$host\"."); + } + else + internal_error("Can't connect to database server \"$host\" as user \"$username\"."); + + if ($host_update) + { + $this->host_update = $host_update; + $this->username = $username; + $this->password = $password; + } +} + + +/** + * Perform an SQL query. + * @see ::safe_sql_query, mysql_query + * @param $sql SQL query + * @return SQL handle or false in case of failure + */ +function sql_query($sql) +{ + debug("it_db::sql_query($sql) on {$this->host}", 5); + + /* + ** If we have a special update host, and an update operation is to be + ** performed, we switch to this host. And we stay forever and ever and ever... + */ + if ($this->host_update && eregi('^(UPDATE|INSERT|REPLACE|DELETE|ALTER) ', $sql)) + { + /*debug('it_db::sql_query(): switching to update host "'.$this->host_update.'"', 3); */ + if ($this->link = @mysql_connect($this->host_update, $this->username, $this->password, true)) + { + if (mysql_select_db($this->name, $this->link)) + $this->host = $this->host_update; + else + internal_error('Error selecting update database "'.$this->name.'" on host "'.$this->host_update.'".'); + + $this->host_update=''; + } + else + internal_error('Error connecting to update database server "'.$this->host_update.'" as user "'.$this->username.'".'); + } + + return mysql_query($sql, $this->link); +} + + +/** + * Perform an SQL query. If the query fails, issue an error message + * and terminate program execution. No matching rows does not mean failure. + * @see ::sql_query, mysql_query + * @param $sql SQL query + * @return SQL handle + */ +function safe_sql_query($sql) +{ + /* debug("it_db::safe_sql_query($sql)", 4); */ + if ($result = $this->sql_query($sql)) + return $result; + else + { + if ($this->errno() == 1062) /* Duplicate entry */ + return 0; + + fail('SQL-Query db "'.$this->name.'" host "'.$this->host."\" failed: \"$sql\":
".$this->error().' ('.$this->errno().')'); + } +} + + +/** + * Free resources used by SQL handle + * @see mysql_free_result + * @param $handle SQL handle + * @return + */ +function free($handle) +{ + return mysql_free_result($handle); +} + + +/** + * Fetch a row as an array + * @see mysql_fetch_array + * @param $handle SQL handle + * @return numeric & associative array with contents of table row + */ +function fetch_array($handle) +{ + return mysql_fetch_array($handle); +} + + +/** + * Fetch a row as an associative array + * @see mysql_fetch_array + * @param $handle SQL handle + * @return associative array with contents of table row + */ +function fetch_assoc($handle) +{ + return mysql_fetch_assoc($handle); +} + + +/** + * Return number of rows of a query + * @see mysql_num_rows + * @param $handle SQL handle + * @return number of rows the query returned + */ +function num_rows($handle) +{ + return mysql_num_rows($handle); +} + + +/** + * Return number of found rows of a limited query that had SQL_COUNT_FOUND_ROWS set + * @return number of rows the query would have returned without LIMIT + */ +function found_rows() +{ + list($count) = mysql_fetch_row($this->safe_sql_query('SELECT FOUND_ROWS()')); + return intval($count); +} + + +/* Internal: get information about tables */ +function _get_table_info() +{ + if ($this->numtables > 0) /* Already done! */ + return; + + if(($tables = mysql_list_tables($this->name,$this->link)) >= 0) + { + $this->numtables = mysql_numrows($tables); + for ($i=0; $i < $this->numtables; ++$i) + { + $name = mysql_tablename($tables, $i); + $this->tablenames[$i] = $name; + } + } + else internal_error("mysql_list_tables($this->name,$this->link) failed."); +} + + +/** + * Return a list of all table names of this database + * @return array with tablenames of this Database + */ +function table_names() +{ + $this->_get_table_info(); + return $this->tablenames; +} + + +/** + * Return number of tables in this database + */ +function num_tables() +{ + $this->_get_table_info(); + return $this->numtables; +} + + +/** + * Return last error number + * @see ::sql_query, ::safe_sql_query, mysql_errno + * @return last mySQL error number + */ +function errno() +{ + return mysql_errno($this->link); +} + + +/** + * Return last error string + * @see ::sql_query, ::safe_sql_query, mysql_error + * @return last mySQL error message + */ +function error() +{ + return mysql_error($this->link); +} + +} /* End class it_db */ +?> diff --git a/db_record.class b/db_record.class new file mode 100644 index 0000000..9470df7 --- /dev/null +++ b/db_record.class @@ -0,0 +1,520 @@ +table = &$table; + $this->keyfieldname = $keyfieldname; +} + + +/** + * Change active key field + * @param $keyfieldname Optional name of primary key field, defaults to 'ID' + */ +function set_key_field($keyfieldname='ID') +{ + $this->keyfieldname = $keyfieldname; + $this->key = isset($this->data[$keyfieldname]) ? $this->data[$keyfieldname] : ''; +} + + +/** + * Select a set of records of this table according to an array of selection + * and sorting criteria. + * Use fetch_next() to iterate through the result set
+ * Example:
+ * $record->select(array('Type' => 'bar', 'Date >=' => '1999-01-01', + * '-Date <' => 'NOW()', 'User NI' => 'chris'), 'ORDER BY Date'); + * + * @param $params optional array of fieldname => value tupels. + * These are ANDed to form a WHERE clause. + * fieldname can contain an operator (separated by space), the + * default operator is '='. The special operator 'NI' specifies + * that the argument must be contained in a comma-separated list. + * + * @param $sql Optional SQL addendum added after $params (ORDER BY etc.) + * @param $fields Optional field list to select (defaults to '*') + * @return Number of rows that matched this query + * @see it_db_record::fetch_next, it_db_table::construct_sql_clause + * + */ +function select($params='', $sql='', $fields='*') +{ + $this->handle = $this->table->safe_sql_select($this->table->construct_sql_clause($params, $sql), $fields); + return $this->table->db->num_rows($this->handle); +} + + +/** + * Post-process data after reading a record. + * This is a stub-function that can be overloaded. + */ +function _read_post_process() +{ +} + + +/** + * Pre-process data before writing a record. + * This is a stub-function that can be overloaded. + * @param $tags Reference to update/create tags, can be modified as needed + */ +function _write_pre_process(&$tags) +{ +} + + +/** + * Fetch the next record of a select() query + * @return true if a record was successfully fetched, false otherwise + * @see it_db_record::select + */ +function fetch_next() +{ + return $this->fetch($this->handle); +} + + +/** + * Fetch the next record from an SQL result into this object. + * If no more records are pending, clear the object's data. + * @param $sqlresult Result of table::sql_select() or similar + * @return 1 if a record was successfully fetched, 0 otherwise + */ +function fetch(&$sqlresult) +{ + $result = 0; + + if ($this->data = $this->table->db->fetch_assoc($sqlresult)) + { + $this->key = $this->data[$this->keyfieldname]; + $result = 1; + } + else + { + $this->key = ""; /* "No record is loaded" */ + $this->data = array(); /* Clear local record data */ + } + + $this->_read_post_process(); + + return $result; +} + + +/** + * Read a record from table + * @param $key key field value of the desired row + * @return 1 on success, 0 otherwise + */ +function read($key) +{ + $result = 0; + + if ($key != "") + { + $result = $this->fetch($this->table->safe_sql_select("WHERE $this->keyfieldname='" . mysql_real_escape_string($key) . "'")); + } + else + { + $this->key = ""; /* "No record is loaded" */ + $this->data = array(); /* Clear local record data */ + } + + $this->_read_post_process(); + + return $result; +} + + +/** + * Create a new record in the table + * @see it_db_record::record_create, it_db_record::safe_create + * @param $tags array of Fieldname/Value pairs + * @param $replace use REPLACE (1) instead of INSERT (otherwise) + * @return MySQL result (0 means failure) + */ +function create($tags, $replace=0) +{ + /* Pre-processing, $tags is passed by reference and may be modified here */ + $this->_write_pre_process($tags); + + $sql = $replace ? "REPLACE" : "INSERT"; + $sql .= " INTO " . $this->table->name . " ("; + $sql2 = ''; + + unset($this->data); + for ($sep=""; $ti = each($tags); $sep=",") + { + /* If the field name starts with '-', the value is taken as raw, no escaping + is done and no quotes are put around it. */ + if (substr($ti[0], 0, 1) == '-') + { + $ti[0] = substr($ti[0], 1); /* Strip that '-' sign */ + $val = $ti[1]; + } + else + $val = isset($ti[1]) ? "'".mysql_real_escape_string($ti[1])."'" : 'NULL'; + + $this->data[$ti[0]] = $ti[1]; /* Store data for later use */ + + $sql .= $sep . $ti[0]; + $sql2 .= "$sep$val"; + } + + $sql .= ") VALUES ($sql2)"; + + if ($result = $this->table->db->sql_query($sql)) + { + /* If the key element was not given, it means it's an AUTO_INCREMENT thingy. */ + if (($this->key = $this->data[$this->keyfieldname]) == "") + { + $result = $this->table->db->safe_sql_query("SELECT LAST_INSERT_ID()"); + $this->key = mysql_result($result, 0, 0); + } + + /* We need all fields from record, not only those we initialised */ + $this->read($this->key); + } + + return $result; +} + + +/** + * Safe version of create (doesn't return in case of failure) + * @see it_db_record::create, it_db_record::record_create + * @param $tags array of Fieldname/Value pairs + * @param $replace use REPLACE (1) instead of INSERT (otherwise) + * @return MySQL result (0 means failure) + */ +function safe_create($tags, $replace=0) +{ + if ($result = $this->create($tags, $replace)) + return $result; + else + fail("it_db_record::safe_create() failed: " . $this->table->db->error()); +} + + +/** + * Update a record in the table + * @param $tags array of Fieldname/Value pairs + * @return MySQL result (0 means failure) + */ +function update($tags) +{ + /* Pre-processing, $tags is passed by reference and may be modified here */ + $this->_write_pre_process($tags); + + if ($this->key == "") + internal_error("it_db_record::update(): can't update undefined record"); + + /* If we have nothing to do, return instead of performing an invalid SQL query */ + if (!count($tags)) + return true; + + $sql = "UPDATE " . $this->table->name . " SET "; + + for ($sep="", $raw=0; $ti = each($tags); $sep=",") + { + /* If the field name starts with '-', the value is taken as raw, no escaping + is done and no quotes are put around it. */ + if (substr($ti[0], 0, 1) == '-') + { + $ti[0] = substr($ti[0], 1); /* Strip that '-' sign */ + $val = $ti[1]; + $raw++; + } + else + $val = "'".mysql_real_escape_string($ti[1])."'"; + + $sql .= $sep.$ti[0].'='.$val; + + if ($ti[0] == $this->key) + { + if ($this->data[$this->keyfieldname] != $ti[0]) + internal_error("$sql: trying to change key from $this->key."); + } + + $this->data[$ti[0]] = $ti[1]; + } + + $sql .= " WHERE " . $this->keyfieldname . "='" . mysql_real_escape_string($this->key) . "'"; + + /* debug("it_db_record::update(): $sql"); */ + $ret = $this->table->db->safe_sql_query($sql); + + /* Only re-read record if necessary (for performance), but always do post-processing. */ + if ($raw) + $this->read($this->key); + else + $this->_read_post_process(); + + return $ret; +} + + +/** + * Delete the current record from the database + * @param $key keyfield value of the record to be deleted. If this is missing, the current record is deleted. + * @return MySQL result (0 means failure) + */ +function delete($key="") +{ + if (!$key) $key = $this->key; + + if (($this->table->name == "") || ($this->keyfieldname == "") || ($key == "")) + internal_error("it_db_record::delete(): no record\n"); + + $sql = "DELETE FROM " . $this->table->name . " WHERE ". $this->keyfieldname . "='" . mysql_real_escape_string($key) . "'"; + if ($result = $this->table->db->sql_query($sql)) + { + $this->key = ""; + $this->data = array(); + } + return $result; +} + + +/** + * Return a field of a record. + * @param $field field name + * @return field value. If the field does not exists, issue an + * error message and terminate program execution. + */ +function safe_get_field($field) +{ + if ($field) + { + if (isset($this->data[$field])) + return $this->data[$field]; + else internal_error("it_db_record::safe_get_field(): field \"$field\" not present in record."); + } + else internal_error("it_db_record::safe_get_field(): empty field name"); +} + + +/** + * Output all fields of a record in (ugly) html format + */ +function dump_html() +{ + echo "
Dump of table " . $this->table->name . ", record " . $this->keyfieldname . " = \"" . $this->key . "\":
\n";
+	reset($this->data); next($this->data);
+	while(list($key, $value) = each($this->data))
+	{
+		if ($key > 0) continue;	/* $$$ ugly */
+		echo $key . " = \"" . htmlspecialchars($value) . "\"\n";
+	}
+	echo "

\n"; +} + + +/** + * Edit a record of a table. Create a new record if necessary.
+ * Example:
+ * $record->edit($id, array('ID' => $id)); + * + * @param $key key value of the row to edit + * @param $fixfields Array of fields not editable (with fixed values) + * @return 1=changed, 2=created, -1=deleted, 0=nothing changed + */ +function edit($key, $fixfields = array()) +{ + $returnresult = 0; + $numfields = $this->table->num_fields(); + + if ($_REQUEST['_COMMAND']) + { + /* + ** If the key field is changed, $key will carry a wrong value, so we + ** take the correct one from $_RECORD_KEY_VALUE + */ + $key = $_REQUEST['_RECORD_KEY_VALUE']; + + switch($_REQUEST['_COMMAND']) + { + case "EDIT": + $this->read($key); + $newdata = array(); + $changes = 0; + for ($i=0; $i < $numfields; ++$i) + { + $fieldname = $this->table->fieldnames[$i]; + + /* Assumes field order is fixed */ + if (isset($fixfields[$fieldname])) + $newvalue = $fixfields[$fieldname]; + else if (is_array($_REQUEST["_RECORD_$fieldname"])) + $newvalue = join(',', $_REQUEST["_RECORD_$fieldname"]); + else + $newvalue = $_REQUEST["_RECORD_$fieldname"]; + + if ($this->data[$fieldname] != $newvalue) + { + $newdata[$fieldname] = $newvalue; + $changes = 1; + } + } + + if ($changes) + { + if ($this->update($newdata)) + { + echo "Änderung erfolgreich durchgeführt.
\n"; + $returnresult = 1; + } + else + fail("Update failed."); + } + else echo "Keine Änderungen.
\n"; + break; + + case "CREATE": + $newdata = array(); + for ($i=0; $i < $numfields; ++$i) + { + $fieldname = $this->table->fieldnames[$i]; + + if (isset($fixfields[$fieldname])) + $newvalue = $fixfields[$fieldname]; + else if (is_array($_REQUEST["_RECORD_$fieldname"])) + $newvalue = join(',', $_REQUEST["_RECORD_$fieldname"]); + else + $newvalue = $_REQUEST["_RECORD_$fieldname"]; + + $newdata[$fieldname] = $newvalue; + } + + if ($this->create($newdata)) + { + $key = $this->key; + echo "Datensatz erzeugt.
\n"; + $returnresult = 2; + } + else + fail("Datensatz konnte nicht erzeugt werden."); + break; + + case "DELETE": + if ($this->delete($key)) + { + echo "Datensatz gelöscht.
\n"; + $returnresult = -1; + } + else + fail("Datensatz konnte nicht gelöscht werden."); + break; + + default: + fail("Unknown _COMMAND \"{$_REQUEST['_COMMAND']}\""); + /* NOT REACHED */ + } + } + + if ($key != "") + { + $this->read($key); + $cmd = "EDIT"; + $buttontext = "Änderungen übernehmen"; + } + else + { + $cmd = "CREATE"; + $buttontext = "Datensatz erzeugen"; + } + + echo "
keyfieldname\">key\">\n"; + echo "\n"; + for ($i=0; $i < $numfields; ++$i) + { + $fieldname = $this->table->fieldnames[$i]; + + /* Do not display fix fields */ + if (isset($fixfields[$fieldname])) + continue; + + $fieldflags = $this->table->fieldflags[$i]; + $fieldlen = $this->table->fieldlengths[$i]; + $size = min($fieldlen, 65); + + if ($fieldname == $this->keyfieldname) + echo ""; + else + echo ""; + + if (strstr($fieldflags, "blob")) + { + if (strlen($this->data["$fieldname"]) < 256) + echo "\n"; + else + echo "\n"; + } + else if (strstr($fieldflags, "enum")) + { + $result = $this->table->db->safe_sql_query("SHOW columns FROM ". $this->table->name . " LIKE '$fieldname'"); + $options = split("'", mysql_result($result, 0, 1)); + + $vals = explode(',', $this->data[$fieldname]); + + for ($j = 0; $j < count($vals); $j++) + $values[$vals[$j]] = 1; + + if (strstr($options[0], 'set')) + $attr = 'multiple'; + else + $attr = 'set="1"'; + + echo "\n"; + } + else + echo "\n"; + } + echo "
$fieldname
$fieldname
data["$fieldname"]) . "\">

\n"; + + if ($this->key != "") + echo "
keyfieldname\">key\">
\n"; + + return $returnresult; +} + +} /* End class it_db_record */ +?> diff --git a/db_table.class b/db_table.class new file mode 100644 index 0000000..f99a733 --- /dev/null +++ b/db_table.class @@ -0,0 +1,425 @@ +db = &$db; + $this->name = $name; +} + + +/** + * Perform a safe SQL SELECT query on this table + * @see it_db::safe_sql_query + * @param $query additional query string, appended at the end of the generated query + * @param $fields comma seperated list of the columns to be returned + */ +function safe_sql_select($query, $fields="*") +{ + return $this->db->safe_sql_query("SELECT $fields FROM " . $this->name . " $query"); +} + + +/** + * Create an SQL query (the stuff after 'WHERE') according to + * an array of selection criteria.
+ * Example:
+ * $sql = $table->construct_sql_clause(array('Type' => 'bar', + * 'Date >=' => '1999-01-01', '-Date <' => 'NOW()', + * 'User NI' => 'chris'), 'ORDER BY Date'); + * + * @param $params optional array of fieldname => value tupels. + * These are ANDed to form a WHERE clause. + * fieldname can contain an operator (separated by space), the + * default operator is '='. The special operator 'NI' specifies + * that the argument must be contained in a comma-separated list. + * @param $sql Optional SQL addendum (added after $params), for ORDER BY etc. + * @param $omit_where (optional) Do not add 'WHERE ' at beginning of result (default: false) + * @return The generated SQL clause + * @see it_db_record::select, it_db_record::fetch_next + */ +function construct_sql_clause($params='', $sql='', $omit_where=false) +{ + if (is_array($params) && (count($params) > 0)) + { + $query = ''; + $sep = ''; + + foreach($params as $field => $value) + { + if (is_int($field)) /* no key specified; just append */ + { + if ($field === $value) /* ignore array(1 => 1) et al */ + continue; + + $query .= " $value"; + } + else + { + $needs_where = true; + + if (!isset($value)) + { + $op = 'IS'; + $qval = 'NULL'; + } + else + { + if (preg_match('/^(\S+)\s+(\S.*)$/', $field, $regs)) + { + $field = $regs[1]; + $op = strtoupper($regs[2]); + } + else + $op = '='; + + /* If the field name starts with '-', the value is taken as raw, + no escaping is done and no quotes are put around it. */ + if (substr($field, 0, 1) == '-') + { + $field = substr($field, 1); /* Strip that '-' sign */ + $qval = $value; + } + else if (!is_array($value)) + $qval = "'".mysql_real_escape_string((string)$value)."'"; + } + + switch ($op) + { + case 'NI': + $query .= $sep."CONCAT(',',$field,',') LIKE '%,$value,%'"; + break; + + case 'IN': + case 'NOT IN': + if (is_array($value)) + { + if ($value) + $query .= "$sep$field $op ('" . join("','", array_map('mysql_real_escape_string', $value)) . "')"; # null is mapped to '' + else + $query .= $sep . "0"; + + break; + } + /* FALLTHROUGH */ + + default: + if (isset($qval)) + $query .= "$sep$field $op $qval"; + else + it::fatal('Undefined $qval when constructing query due to invalid $value (array)'); + break; + } + $sep = ' AND '; + } + } + + if ($needs_where && !$omit_where) + $query = 'WHERE '.$query; + + if ($sql) + $query .= ' '; + } + $query .= $sql; + + return $query; +} + + +/** + * Return the count of rows on this table with optional WHERE clause + * @param $where Optional WHERE clause to narrow the set of rows to count + * @return Number of rows matching the WHERE clause + */ +function count($where='') +{ + $result = $this->safe_sql_select($where, 'COUNT(*)'); + $row = $this->db->fetch_assoc($result); + return $row['COUNT(*)']; +} + + +/* Internal: get information about fields */ +function _get_field_info() +{ + if ($this->numfields > 0) /* Already done! */ + return; + + if(($fields = mysql_list_fields($this->db->name, $this->name, $this->db->link)) >= 0) + { + $this->numfields = mysql_num_fields($fields); + for ($i=0; $i < $this->numfields; ++$i) + { + $name = mysql_field_name($fields, $i); + $this->fieldnames[$i] = $name; + $this->fieldtypes[$i] = $this->fieldtypes[$name] = mysql_field_type($fields, $i); + $this->fieldlengths[$i] = $this->fieldlengths[$name] = mysql_field_len($fields, $i); + $this->fieldflags[$i] = $this->fieldflags[$name] = mysql_field_flags($fields, $i); + /* debug("name='" . $this->fieldnames[$i] . "', len=" . $this->fieldlengths[$i] . ", type='" . $this->fieldtypes[$i] . "', flags='" . $this->fieldflags[$i] . "'\n", 6); */ + } + } + else internal_error("mysql_list_fields($this->db->name, $this->name, $this->db->link) failed."); +} + + +/** + * Return a comma separated list of all field names of this table + */ +function field_names() +{ + $result = ''; + $this->_get_field_info(); + for ($i=0; $i < $this->numfields; ++$i) + { + if ($i > 0) $result .= ","; + $result .= $this->fieldnames[$i]; + } + return $result; +} + + +/** + * Return the length of a field + * @param $fieldname Name of the field + */ +function get_field_length($name) +{ + $this->_get_field_info(); + return $this->fieldlengths[$name]; +} + + +/** + * Return number of fields of a record of this table + */ +function num_fields() +{ + $this->_get_field_info(); + return $this->numfields; +} + + +/** + * Variable name used to propagate sort criteria + */ +function get_sort_variable_name() +{ + return "Sort" . md5($this->db->name . $this->name); +} + + +/** + * Print an SQL table as an HTML table. Supports user-sorting by column, + * limited WHERE clause, lists of fields to display and header texts, and + * a list of links for each field. + * @param $tableargs format string for the table or "" for default + * @param $sqlwhere SQL WHERE clause to restrict elements + * @param $c_fields comma seperated list of the fields to print + * @param $c_descriptions comma seperated list of the header labels to print + * @param $c_links dito with links to the respective elements + * @param $default_order default sort order: "fieldname" or "fieldname DESC" + * @param $rows_limit limit and position: "10" or "20,5" + */ +function dump_html($tableargs="", $sqlwhere="", $c_fields="", $c_descriptions="", $c_links="", $default_order="", $rows_limit="", $thispage="", $strip_tags=0) +{ + /* Unique identifier of this table */ + $table_sort = $this->get_sort_variable_name(); + + /* Default HTML table */ + if ($tableargs=="") + $tableargs="border=1 cellspacing=0 cellpadding=5"; + + /* Default field list: show them all */ + if ($c_fields == "") + $c_fields = $this->field_names(); + + /* Default list title: Field names */ + if ($c_descriptions == "") + $c_descriptions = $c_fields; + + $fields = split(",", $c_fields); + $descriptions = split(",", $c_descriptions); + $links = split(",", $c_links); + $numfields = count($fields); + + /* Default sort criterium: Ascending sort by first column */ + if ($default_order == "") + $default_order = $fields[0]; + + if ($GLOBALS[$table_sort] == "") + $GLOBALS[$table_sort] = $default_order; + + $sql = "SELECT $c_fields FROM $this->name"; + + if ($sqlwhere) + $sql .= " WHERE $sqlwhere"; + + $sql .= " ORDER BY $GLOBALS[$table_sort]"; + + if ($rows_limit != "") + $sql .= " LIMIT $rows_limit"; + + $result = $this->db->safe_sql_query($sql); + + if ($this->db->num_rows($result) == 0) + { + if (is_object($GLOBALS['it_text'])) + echo T("db_NoObjectsFound"). "
\n"; + return; + } + + echo "\n"; + + if (empty($thispage)) $thispage = $GLOBALS['PHP_SELF']; + if (strstr($thispage, "?")) $thispage .= "&"; else $thispage .= "?"; + + /* Wenn man keine Titelzeile will, für c_descriptions einfach "," angeben */ + if ($descriptions[0]) + { + echo ''; + for ($i=0; $i < $numfields; ++$i) + { + if ($GLOBALS[$table_sort] == $fields[$i]) + { + $newsort = "$GLOBALS[$table_sort]+DESC"; + $sortimg = ''; + } + else if ($GLOBALS[$table_sort] == "$fields[$i] DESC") + { + $newsort = $fields[$i]; + $sortimg = ''; + } + else + { + $newsort = $fields[$i]; + $sortimg = ''; + } + + echo "\n"; + } + echo "\n"; + } + + while ($f = $this->db->fetch_array($result)) + { + echo ""; + for ($i=0; $i<$numfields; ++$i) + { + $fieldspec = $f[$fields[$i]]; + if (!$fieldspec) $fieldspec = "  "; + if ($fieldspec == "0.00") $fieldspec = "-"; + /*if (strlen($fieldspec) > 80) $fieldspec = substr($fieldspec, 0, 80) . "..."; */ + + if (isset($links[$i])) + { + if (strstr($links[$i], "?")) $ch = "&"; else $ch = "?"; + $anchor=""; + $anchor2=""; + } + else + $anchor = $anchor2 = ""; + + if ($strip_tags) + $fieldspec = strip_tags($fieldspec); + echo ""; + } + echo "\n"; + } + echo "
\n"; + echo "\n\n"; + echo ''; + echo ''; + echo "\n
'. $descriptions[$i] .''. $sortimg .'
\n"; + echo "
$anchor" . $fieldspec . "$anchor2
\n"; +} + + +/** + * Make a 'select form field' ("Select-Form-Feld") from a table and pre-select an entry + * @param $name Name of FORM object to generate + * @param $selected Selected record + * @param $globaloption Option to add as first value, syntax: key,text + * @param $optionfield Table field to use for option keys + * @param $descriptionfield Table field to display + * @param $query SQL Query after "FROM ...", defaults to "ORDER BY $descriptionfield" + */ +function make_select($name, $selected, $globaloption, $optionfield, $descriptionfield, $query="") +{ + $globalopt = split(",", $globaloption); + + if (empty($query)) + $query = "ORDER BY $descriptionfield"; + $query = "SELECT * FROM $this->name $query"; + + echo "\n"; +} + + +/** + * Drops the current table from the database + * @return MySQL result (0 means failure) + */ +function drop() +{ + if ($this->name == '') + internal_error("it_db_table::drop(): no table\n"); + + if ($result = $this->db->sql_query('DROP TABLE IF EXISTS '.$this->name)) + { + $this->name = ''; + $numfields = 0; + $fieldnames = array(); + $fieldtypes = array(); + $fieldlengths = array(); + $fieldflags = array(); + } + + return $result; +} + +} /* End class it_db_table */ +?> diff --git a/dbi.class b/dbi.class new file mode 100644 index 0000000..c6469fe --- /dev/null +++ b/dbi.class @@ -0,0 +1,450 @@ + null, + 'server' => "localhost", + 'user' => "itools", + 'pw' => "24%^jXC~", + 'safety' => 1, /* 0= never die, 1=die if query invalid, 2=die also if no results */ + 'keyfield' => "ID", + 'createclasses' => false, + 'classprefix' => "", + 'autoincrement' => true, + 'randomid' => false, + 'sqllog' => false, + 'persistent' => false, + ); + + # Key of currently loaded record or null (public readonly) + var $_key; + + # Array of name => length of table fields + var $_fields; + + +/** + * Constructor: Initialize the DBI interface + * @param $config array(key => value) of configuration data + * @param $query Optional initial query to run + */ +function it_dbi($config, $query = null) +{ + # Shortcut: String config means use this table with default values + if (!is_array($config)) + $config = array('table' => $config); + + # Create current settings + foreach ($config + $this->_defaultconfig as $key => $value) + { + $var = "_$key"; + $this->$var = $value; + } + unset($this->_defaultconfig); /* to shorten print_r() output */ + + if (!isset($this->_db)) + $this->_db = $GLOBALS['ULTRADB']; + + $dbid = "$this->_db/$this->_server/$this->_user"; + + if (!($this->_link = $GLOBALS['it_dbi_link'][$dbid])) + { + # Use persistent connections but prevent reuse if only DB differs + if (!$this->_persistent || $GLOBALS['it_dbi_connected']["$this->_server/$this->_user"]++) + $this->_link = @mysql_connect($this->_server, $this->_user, $this->_pw, true); + else + $this->_link = @mysql_pconnect($this->_server, $this->_user, $this->_pw); + + if (!$this->_link) + { + # One retry after a short delay (always non-persistent) + it::log('sqllog', "it_dbi(): retrying DB link (mysql_connect $this->_server, $this->_db): " . mysql_error()); + sleep(1); + $this->_link = @mysql_connect($this->_server, $this->_user, $this->_pw, true); + } + + if (!$this->_link) + $this->_fatal("it_dbi(): can't create DB link (mysql_connect $this->_server, $this->_db): " . mysql_error()); + + if (!(@mysql_select_db($this->_db, $this->_link))) + $this->_fatal("it_dbi(): can't select database \"$this->_db\": " . mysql_error($this->_link)); + + $GLOBALS['it_dbi_link'][$dbid] = $this->_link; + } + + if ($this->_createclasses) + { + if (!($tables = mysql_list_tables($this->_db, $this->_link))) + $this->_fatal("it_dbi(): can't list on tables \"$this->_db\": " . mysql_error($this->_link)); + + $defaults = ''; + foreach($config as $key => $value) + if ($key != 'createclasses') + $defaults .= "'$key' => '".strtr($value, array('\'' => '\\\'', '$' => '\\