]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/msql.php
Removed debug output; improved error messages. pages with backslashes
[SourceForge/phpwiki.git] / lib / msql.php
1 <?php rcs_id('$Id: msql.php,v 1.6.2.7 2001-11-16 02:53:21 wainstead Exp $');
2
3    /*
4       Database functions:
5       MakePageHash($dbhash)
6       MakeDBHash($pagename, $pagehash)
7       OpenDataBase($dbname)
8       CloseDataBase($dbi)
9       RetrievePage($dbi, $pagename, $pagestore)
10       InsertPage($dbi, $pagename, $pagehash)
11       SaveCopyToArchive($dbi, $pagename, $pagehash) 
12       IsWikiPage($dbi, $pagename)
13       InitTitleSearch($dbi, $search)
14       TitleSearchNextMatch($dbi, &$pos)
15       InitFullSearch($dbi, $search)
16       FullSearchNextMatch($dbi, &$pos)
17       MakeBackLinkSearchRegexp($pagename)
18       InitBackLinkSearch($dbi, $pagename) 
19       BackLinkSearchNextMatch($dbi, &$pos) 
20       GetAllWikiPageNames($dbi)
21    */
22
23
24    // open a database and return the handle
25    // ignores MAX_DBM_ATTEMPTS
26
27    function OpenDataBase($dbinfo) {
28       global $msql_db;
29
30       if (! ($dbc = msql_connect())) {
31          $msg = gettext ("Cannot establish connection to database, giving up.");
32          $msg .= "<BR>";
33          $msg .= sprintf(gettext ("Error message: %s"), msql_error());
34          ExitWiki($msg);
35       }
36       if (!msql_select_db($msql_db, $dbc)) {
37          $msg = gettext ("Cannot open database %s, giving up.");
38          $msg .= "<BR>";
39          $msg .= sprintf(gettext ("Error message: %s"), msql_error());
40          ExitWiki($msg);
41       }
42
43       $dbi['dbc'] = $dbc;
44       $dbi['table'] = $dbinfo['table'];           // page metadata
45       $dbi['page_table'] = $dbinfo['page_table']; // page content
46       return $dbi;
47    }
48
49
50    function CloseDataBase($dbi) {
51       // I found msql_pconnect unstable so we go the slow route.
52       return msql_close($dbi['dbc']);
53    }
54
55
56    // This should receive the full text of the page in one string
57    // It will break the page text into an array of strings
58    // of length MSQL_MAX_LINE_LENGTH which should match the length
59    // of the columns wikipages.LINE, archivepages.LINE in schema.minisql
60
61    function msqlDecomposeString($string) {
62       $ret_arr = array();
63
64       // initialize the array to satisfy E_NOTICE
65       for ($i = 0; $i < MSQL_MAX_LINE_LENGTH; $i++) {
66          $ret_arr[$i] = "";
67       }
68       $el = 0;
69    
70       // zero, one, infinity
71       // account for the small case
72       if (strlen($string) < MSQL_MAX_LINE_LENGTH) { 
73          $ret_arr[$el] = $string;
74          return $ret_arr;
75       }
76    
77       $words = array();
78       $line = $string2 = "";
79    
80       // split on single spaces
81       $words = preg_split("/ /", $string);
82       $num_words = count($words);
83    
84       reset($words);
85       $ret_arr[0] = $words[0];
86       $line = " $words[1]";
87    
88       // for all words, build up lines < MSQL_MAX_LINE_LENGTH in $ret_arr
89       for ($x = 2; $x < $num_words; $x++) {
90          $length = strlen($line) + strlen($words[$x]) 
91                    + strlen($ret_arr[$el]) + 1;
92
93          if ($length < MSQL_MAX_LINE_LENGTH) {
94             $line .= " " .  $words[$x];
95          } else {
96             // put this line in the return array, reset, continue
97             $ret_arr[$el++] .= $line;
98             $line = " $words[$x]"; // reset     
99          }
100       }
101       $ret_arr[$el] = $line;
102       return $ret_arr;
103    }
104
105
106    // Take form data and prepare it for the db
107    function MakeDBHash($pagename, $pagehash)
108    {
109       $pagehash["pagename"] = addslashes($pagename);
110       if (!isset($pagehash["flags"]))
111          $pagehash["flags"] = 0;
112       if (!isset($pagehash["content"])) {
113          $pagehash["content"] = array();
114       } else {
115          $pagehash["content"] = implode("\n", $pagehash["content"]);
116          $pagehash["content"] = msqlDecomposeString($pagehash["content"]);
117       }
118       $pagehash["author"] = addslashes($pagehash["author"]);
119       if (empty($pagehash["refs"])) {
120          $pagehash["refs"] = "";
121       } else {
122          $pagehash["refs"] = serialize($pagehash["refs"]);
123       }
124
125       return $pagehash;
126    }
127
128
129    // Take db data and prepare it for display
130    function MakePageHash($dbhash)
131    {
132       // unserialize/explode content
133       $dbhash['refs'] = unserialize($dbhash['refs']);
134       return $dbhash;
135    }
136
137
138    // Return hash of page + attributes or default
139    function RetrievePage($dbi, $pagename, $pagestore) {
140       $pagename = addslashes($pagename);
141       $table = $pagestore['table'];
142       $pagetable = $pagestore['page_table'];
143
144       $query = "select * from $table where pagename='$pagename'";
145       // echo "<p>query: $query<p>";
146       $res = msql_query($query, $dbi['dbc']);
147       if (msql_num_rows($res)) {
148          $dbhash = msql_fetch_array($res);
149
150          $query = "select lineno,line from $pagetable " .
151                   "where pagename='$pagename' " .
152                   "order by lineno";
153
154          $msql_content = "";
155          if ($res = msql_query($query, $dbi['dbc'])) {
156             $dbhash["content"] = array();
157             while ($row = msql_fetch_array($res)) {
158                 $msql_content .= $row["line"];
159             }
160             $dbhash["content"] = explode("\n", $msql_content);
161          }
162
163          return MakePageHash($dbhash);
164       }
165       return -1;
166    }
167
168
169    // Either insert or replace a key/value (a page)
170    function InsertPage($dbi, $pagename, $pagehash) {
171
172       $pagehash = MakeDBHash($pagename, $pagehash);
173       // $pagehash["content"] is now an array of strings 
174       // of MSQL_MAX_LINE_LENGTH
175
176       // record the time of modification
177       $pagehash["lastmodified"] = time();
178
179       if (IsWikiPage($dbi, $pagename)) {
180
181          $PAIRS = "author='$pagehash[author]'," .
182                   "created=$pagehash[created]," .
183                   "flags=$pagehash[flags]," .
184                   "lastmodified=$pagehash[lastmodified]," .
185                   "pagename='$pagehash[pagename]'," .
186                   "refs='$pagehash[refs]'," .
187                   "version=$pagehash[version]";
188
189          $query  = "UPDATE $dbi[table] SET $PAIRS WHERE pagename='$pagename'";
190
191       } else {
192          // do an insert
193          // build up the column names and values for the query
194
195          $COLUMNS = "author, created, flags, lastmodified, " .
196                     "pagename, refs, version";
197
198          $VALUES =  "'$pagehash[author]', " .
199                     "$pagehash[created], $pagehash[flags], " .
200                     "$pagehash[lastmodified], '$pagehash[pagename]', " .
201                     "'$pagehash[refs]', $pagehash[version]";
202
203
204          $query = "INSERT INTO $dbi[table] ($COLUMNS) VALUES($VALUES)";
205       }
206
207       // echo "<p>Query: $query<p>\n";
208
209       // first, insert the metadata
210       $retval = msql_query($query, $dbi['dbc']);
211       if ($retval == false) {
212          printf(gettext ("Insert/update to table 'wiki' failed: %s"), msql_error());
213          print "<br>\n";
214       }
215
216
217       // second, insert the page data
218       // remove old data from page_table
219       $query = "delete from $dbi[page_table] where pagename='$pagename'";
220       // echo "Delete query: $query<br>\n";
221       $retval = msql_query($query, $dbi['dbc']);
222       if ($retval == false) {
223          printf(gettext ("Delete on %s failed: %s"), $dbi[page_table],
224             msql_error());
225          print "<br>\n";
226       }
227
228       // insert the new lines
229       reset($pagehash["content"]);
230
231       for ($x = 0; $x < count($pagehash["content"]); $x++) {
232          $line = addslashes($pagehash["content"][$x]);
233          if ($line == '') continue; // why do we always have 127 lines?
234          $esc_pagename = addslashes($pagename);
235          $query = "INSERT INTO $dbi[page_table] " .
236                   "(pagename, lineno, line) " .
237                   "VALUES('$esc_pagename', $x, '$line')";
238          //echo "Page line insert query: $query<br>\n";
239          $retval = msql_query($query, $dbi['dbc']);
240          if ($retval == false) { 
241             printf(gettext ("Insert into %s failed: %s"), $dbi[page_table],
242                msql_error());
243             print "<br>\n";
244          }
245       }
246    }
247
248
249    // for archiving pages to a separate table
250    function SaveCopyToArchive($dbi, $pagename, $pagehash) {
251       global $ArchivePageStore;
252
253       $pagehash = MakeDBHash($pagename, $pagehash);
254       // $pagehash["content"] is now an array of strings 
255       // of MSQL_MAX_LINE_LENGTH
256
257       if (IsInArchive($dbi, $pagename)) {
258
259          $PAIRS = "author='$pagehash[author]'," .
260                   "created=$pagehash[created]," .
261                   "flags=$pagehash[flags]," .
262                   "lastmodified=$pagehash[lastmodified]," .
263                   "pagename='$pagehash[pagename]'," .
264                   "refs='$pagehash[refs]'," .
265                   "version=$pagehash[version]";
266
267          $query  = "UPDATE $ArchivePageStore[table] SET $PAIRS WHERE pagename='$pagename'";
268
269       } else {
270          // do an insert
271          // build up the column names and values for the query
272
273          $COLUMNS = "author, created, flags, lastmodified, " .
274                     "pagename, refs, version";
275
276          $VALUES =  "'$pagehash[author]', " .
277                     "$pagehash[created], $pagehash[flags], " .
278                     "$pagehash[lastmodified], '$pagehash[pagename]', " .
279                     "'$pagehash[refs]', $pagehash[version]";
280
281
282          $query = "INSERT INTO archive ($COLUMNS) VALUES($VALUES)";
283       }
284
285       // echo "<p>Query: $query<p>\n";
286
287       // first, insert the metadata
288       $retval = msql_query($query, $dbi['dbc']);
289       if ($retval == false) {
290          printf(gettext ("Insert/update into table 'archive' failed: %s"), msql_error());
291          print "<br>\n";
292       }
293
294       // second, insert the page data
295       // remove old data from page_table
296       $query = "delete from $ArchivePageStore[page_table] where pagename='$pagename'";
297       // echo "Delete query: $query<br>\n";
298       $retval = msql_query($query, $dbi['dbc']);
299       if ($retval == false) {
300          printf(gettext ("Delete on %s failed: %s"),
301           $ArchivePageStore[page_table], msql_error());
302          print "<br>\n";
303       }
304
305       // insert the new lines
306       reset($pagehash["content"]);
307
308       for ($x = 0; $x < count($pagehash["content"]); $x++) {
309          $line = addslashes($pagehash["content"][$x]);
310          $query = "INSERT INTO $ArchivePageStore[page_table] " .
311                   "(pagename, lineno, line) " .
312                   "VALUES('$pagename', $x, '$line')";
313          // echo "Page line insert query: $query<br>\n";
314          $retval = msql_query($query, $dbi['dbc']);
315          if ($retval == false) {
316             printf(gettext ("Insert into %s failed: %s"),
317               $ArchivePageStore[page_table], msql_error());
318             print "<br>\n";
319          }
320       }
321
322
323    }
324
325
326    function IsWikiPage($dbi, $pagename) {
327       $pagename = addslashes($pagename);
328       $query = "select pagename from wiki where pagename='$pagename'";
329       // echo "Query: $query<br>\n";
330       if ($res = msql_query($query, $dbi['dbc'])) {
331          return(msql_affected_rows($res));
332       }
333    }
334
335
336    function IsInArchive($dbi, $pagename) {
337       $pagename = addslashes($pagename);
338       $query = "select pagename from archive where pagename='$pagename'";
339       // echo "Query: $query<br>\n";
340       if ($res = msql_query($query, $dbi['dbc'])) {
341          return(msql_affected_rows($res));
342       }
343    }
344
345
346
347    // setup for title-search
348    function InitTitleSearch($dbi, $search) {
349       $search = preg_replace('/(?=[%_\\\\])/', "\\", $search);
350       $search = addslashes($search);
351       $query = "select pagename from $dbi[table] " .
352                "where pagename clike '%$search%' order by pagename";
353       $res = msql_query($query, $dbi['dbc']);
354
355       return $res;
356    }
357
358
359    // iterating through database
360    function TitleSearchNextMatch($dbi, $res) {
361       if($o = msql_fetch_object($res)) {
362          return $o->pagename;
363       }
364       else {
365          return 0;
366       }
367    }
368
369
370    // setup for full-text search
371    function InitFullSearch($dbi, $search) {
372       // select unique page names from wikipages, and then 
373       // retrieve all pages that come back.
374       $search = preg_replace('/(?=[%_\\\\])/', "\\", $search);
375       $search = addslashes($search);
376       $query = "select distinct pagename from $dbi[page_table] " .
377                "where line clike '%$search%' " .
378                "order by pagename";
379       $res = msql_query($query, $dbi['dbc']);
380
381       return $res;
382    }
383
384    // iterating through database
385    function FullSearchNextMatch($dbi, $res) {
386       global $WikiPageStore;
387       if ($row = msql_fetch_row($res)) {
388         return RetrievePage($dbi, $row[0], $WikiPageStore);
389       } else {
390         return 0;
391       }
392    }
393
394    ////////////////////////
395    // new database features
396
397    // Compute PCRE suitable for searching for links to the given page.
398    function MakeBackLinkSearchRegexp($pagename) {
399       global $WikiNameRegexp;
400
401       // Note that in (at least some) PHP 3.x's, preg_quote only takes
402       // (at most) one argument.  Also it doesn't quote '/'s.
403       // It does quote '='s, so we'll use that for the delimeter.
404       $quoted_pagename = preg_quote($pagename);
405       if (preg_match("/^$WikiNameRegexp\$/", $pagename)) {
406          # FIXME: This may need modification for non-standard (non-english) $WikiNameRegexp.
407          return "=(?<![A-Za-z0-9!])$quoted_pagename(?![A-Za-z0-9])=";
408       }
409       else {
410          // Note from author: Sorry. :-/
411          return ( '='
412                   . '(?<!\[)\[(?!\[)' // Single, isolated '['
413                   . '([^]|]*\|)?'     // Optional stuff followed by '|'
414                   . '\s*'             // Optional space
415                   . $quoted_pagename  // Pagename
416                   . '\s*\]=' );       // Optional space, followed by ']'
417          // FIXME: the above regexp is still not quite right.
418          // Consider the text: " [ [ test page ]".  This is a link to a page
419          // named '[ test page'.  The above regexp will recognize this
420          // as a link either to '[ test page' (good) or to 'test page' (wrong).
421       } 
422    }
423
424    // setup for back-link search
425    function InitBackLinkSearch($dbi, $pagename) {
426       global $WikiLinksStore;
427      
428       $topage = addslashes($pagename);
429       $res[arr] = array();
430
431       // FIXME: this is buggy.  If a [multiword link] is split accross
432       // multiple lines int the page_table, we wont find it.
433       // (Probably the best fix is to implement the link table, and use it.)
434       $res['regexp'] = MakeBackLinkSearchRegexp($pagename);
435       $query = "SELECT pagename, line FROM $dbi[page_table]"
436            . " WHERE line LIKE '%$topage%'"
437            . " ORDER BY pagename";
438       
439       //echo "<p>$query<p>\n";
440       $res['res'] = msql_query($query, $dbi["dbc"]);
441
442       $count = 0;
443       $arr = array();
444
445       // build an array of the results.
446       while ($hash = msql_fetch_array($res[res]) ) {
447           if ($arr[$count -1 ] == $hash[pagename])
448               continue;
449           $arr[$count] = $hash[pagename];
450           $count++;
451       }
452
453       $res[count] = 0;
454       reset($arr);
455       $res[arr] = $arr;
456       
457       return $res;
458    }
459
460
461 // iterating through database
462 function BackLinkSearchNextMatch($dbi, &$res) {
463
464     if ($res[count] > count($res[arr]))
465         return 0;
466
467     $retval = $res[arr][$res[count]];
468     $res[count]++;
469
470     return $retval;
471 }
472
473 /*
474             if ( ($o = msql_fetch_object($res['res'])) == FALSE ) {
475             echo "returning zero<p>\n";
476             echo "it's '$o' <p>\n";
477             return 0;
478             }
479             if ( $res['lastpage'] == $o->pagename )
480             continue;
481             if ( ! preg_match($res['regexp'], $a->line) )
482             continue;
483             $res['lastpage'] = $o->pagename;
484             return $o->pagename;
485             }
486           */
487
488
489    function IncreaseHitCount($dbi, $pagename) {
490
491       $qpagename = addslashes($pagename);
492       $query = "select hits from hitcount where pagename='$qpagename'";
493       $res = msql_query($query, $dbi['dbc']);
494       if (msql_num_rows($res)) {
495          $hits = msql_result($res, 0, 'hits');
496          $hits++;
497          $query = "update hitcount set hits=$hits where pagename='$qpagename'";
498          $res = msql_query($query, $dbi['dbc']);
499
500       } else {
501          $query = "insert into hitcount (pagename, hits) " .
502                   "values ('$qpagename', 1)";
503          $res = msql_query($query, $dbi['dbc']);
504       }
505
506       return $res;
507    }
508
509    function GetHitCount($dbi, $pagename) {
510
511       $qpagename = addslashes($pagename);
512       $query = "select hits from hitcount where pagename='$qpagename'";
513       $res = msql_query($query, $dbi['dbc']);
514       if (msql_num_rows($res)) {
515          $hits = msql_result($res, 0, 'hits');
516       } else {
517          $hits = "0";
518       }
519
520       return $hits;
521    }
522
523
524
525    function InitMostPopular($dbi, $limit) {
526
527       $query = "select * from hitcount " .
528                "order by hits desc, pagename limit $limit";
529
530       $res = msql_query($query, $dbi['dbc']);
531       
532       return $res;
533    }
534
535    function MostPopularNextMatch($dbi, $res) {
536
537       if ($hits = msql_fetch_array($res)) {
538          return $hits;
539       } else {
540          return 0;
541       }
542    }
543
544    function GetAllWikiPageNames($dbi_) {
545       $res = msql_query("select pagename from wiki", $dbi['dbc']);
546       $rows = msql_num_rows($res);
547       for ($i = 0; $i < $rows; $i++) {
548          $pages[$i] = msql_result($res, $i, 'pagename');
549       }
550       return $pages;
551    }
552
553    ////////////////////////////////////////
554    // functionality for the wikilinks table
555
556    // takes a page name, returns array of scored incoming and outgoing links
557
558 /* Not implemented yet. The code below was copied from mysql.php...
559
560    function GetWikiPageLinks($dbi, $pagename) {
561       $links = array();
562       $pagename = addslashes($pagename);
563       $res = msql_query("select wikilinks.topage, wikiscore.score from wikilinks, wikiscore where wikilinks.topage=wikiscore.pagename and wikilinks.frompage='$pagename' order by score desc, topage", $dbi['dbc']);
564
565       $rows = msql_num_rows($res);
566       for ($i = 0; $i < $rows; $i++) {
567          $out = msql_fetch_array($res);
568          $links['out'][] = array($out['topage'], $out['score']);
569       }
570
571       $res = msql_query("select wikilinks.frompage, wikiscore.score from wikilinks, wikiscore where wikilinks.frompage=wikiscore.pagename and wikilinks.topage='$pagename' order by score desc, frompage", $dbi['dbc']);
572       $rows = msql_num_rows($res);
573       for ($i = 0; $i < $rows; $i++) {
574          $out = msql_fetch_array($res);
575          $links['in'][] = array($out['frompage'], $out['score']);
576       }
577
578       $res = msql_query("select distinct hitcount.pagename, hitcount.hits from wikilinks, hitcount where (wikilinks.frompage=hitcounts.pagename and wikilinks.topage='$pagename') or (wikilinks.topage=pagename and wikilinks.frompage='$pagename') order by hitcount.hits desc, wikilinks.pagename", $dbi['dbc']);
579       $rows = msql_num_rows($res);
580       for ($i = 0; $i < $rows; $i++) {
581          $out = msql_fetch_array($res);
582          $links['popular'][] = array($out['pagename'], $out['hits']);
583       }
584
585       return $links;
586    }
587
588
589    // takes page name, list of links it contains
590    // the $linklist is an array where the keys are the page names
591    function SetWikiPageLinks($dbi, $pagename, $linklist) {
592       $frompage = addslashes($pagename);
593
594       // first delete the old list of links
595       msql_query("delete from wikilinks where frompage='$frompage'",
596                 $dbi["dbc"]);
597
598       // the page may not have links, return if not
599       if (! count($linklist))
600          return;
601       // now insert the new list of links
602       while (list($topage, $count) = each($linklist)) {
603          $topage = addslashes($topage);
604          if($topage != $frompage) {
605             msql_query("insert into wikilinks (frompage, topage) " .
606                      "values ('$frompage', '$topage')", $dbi["dbc"]);
607          }
608       }
609
610       msql_query("delete from wikiscore", $dbi["dbc"]);
611       msql_query("insert into wikiscore select w1.topage, count(*) from wikilinks as w1, wikilinks as w2 where w2.topage=w1.frompage group by w1.topage", $dbi["dbc"]);
612    }
613 */
614
615 ?>