source: trunk/tools/database/www/cvs.php3@ 3950

Last change on this file since 3950 was 3950, checked in by bird, 25 years ago

More coding.

File size: 37.8 KB
Line 
1<?php
2
3require "../Odin32DBhelpers.php3";
4
5/*
6 * Configuration:
7 */
8$sCVSROOT = ".";
9$sCVSROOT = "d:/odin32/cvs/cvsroot";
10
11
12/**
13 * Quick and dirty CVS file parser.
14 */
15class CVSFile
16{
17 var $fOk; /* Status of contructor. */
18 var $sError; /* Last error message. */
19 var $sFullName; /* Full path of the */
20 var $sDir; /* CVSROOT relative directory */
21 var $sName; /* Workfile filename. */
22 var $sExt; /* Workfile extention. */
23 var $aasKeys; /* base keys */
24 var $aasDeltas; /* the text values only */
25 var $aaasRevs; /* all types of revision info (but the text) */
26
27
28 /**
29 * Constructor.
30 * Opens a CVS repository file, reads it into memory and closes it.
31 */
32 function CVSFile($sFilename, $fNoDeltas)
33 {
34 global $sCVSROOT;
35
36 $timer = Odin32DBTimerStart("");
37
38 $this->fOk = 0;
39 /*
40 * TODO: Security: Check that the path and filename is valid!
41 * We can't allow relative paths (ie. "..")
42 */
43 if (strlen($sFilename) < 3 || substr($sFilename, strlen($sFilename)-2) != ",v")
44 {
45 $this->sError = "filename is invalid";
46 return 1;
47 }
48
49 /*
50 * Check filesize. Minimum size is 10 bytes!
51 */
52 $this->sFullname = $sCVSROOT."/".$sFilename;
53 $cbFile = filesize($this->sFullname);
54 if ($cbFile <= 10)
55 {
56 $this->sError = "too small file, " . $this->sFullname . ", ". $cbFile ."\n";
57 return 1;
58 }
59 if (!$fNoDeltas && $cbFile >= (2*1024*1024)) //currently max size of 2MB.
60 {
61 $this->sError = "\ntoo large file, ". $this->sFullname .", ". $cbFile ."\n";
62 return 1;
63 }
64
65
66 /*
67 * Seems ok. Let's, init object variables
68 */
69 $this->fOk = 0;
70 $this->sError = "";
71 $i = strrpos($sFilename, "\\");
72 $j = strrpos($sFilename, "/");
73 $i = ($i > $j) ? $i : $j;
74 $this->sName = substr($sFilename, $i > 0 ? $i + 1 : 0, strlen($sFilename)-2 - ($i > 0 ? $i + 1 : 0));
75 $this->sDir = substr($sFilename, 0, $i);
76 if (($i = strrpos($this->sName, '.')) > 0)
77 $this->sExt = substr($this->sName, $i+1);
78 else
79 $this->sExt = "";
80 $this->aasKeys = array();
81 $this->aasDeltas = array();
82 $this->aaasRevs = array();
83
84
85 /*
86 * Open the file
87 */
88 $hFile = fopen($this->sFullname, "rb");
89 if (!$hFile)
90 {
91 $this->sError = "\nfailed to open the file $this->sFullname\n";
92 fclose($hFile);
93 return 1;
94 }
95
96
97 /*
98 * Parse file.
99 */
100 $fAt = 0;
101 $fNewKey= 1;
102 $sKey = "";
103 $sRev = "";
104 $fDesc = 0;
105
106 $iLine = -1;
107 $sLine = "";
108 $fStop = 0;
109 while (($sLine != "" || !feof($hFile)) && !$fStop)
110 {
111 /*
112 * Left trim.
113 * If empty line, get next and iterate.
114 */
115 $sLine = ltrim($sLine);
116 if (!$sLine || $sLine == "" || $sLine == "\n" || $sLine == "\r")
117 {
118 $iLine++;
119 $sLine = fgets($hFile, 0x1000);
120 continue;
121 }
122
123 /*
124 * Are we looking for a new key word?
125 */
126 if ($fNewKey)
127 {
128 //$sKey = CopyWord($sLine);
129 $cch = strlen($sLine);
130 for ($i = 0; $i < $cch; $i++)
131 {
132 $c = $sLine[$i];
133 if (!(
134 ($c >= 'a' && $c <= 'z')
135 ||
136 ($c >= 'A' && $c <= 'Z')
137 ||
138 ($c >= '0' && $c <= '9')
139 ||
140 $c == '.'
141 ||
142 $c == '_'
143 )
144 )
145 break;
146 }
147 $sKey = substr($sLine, 0, $i);
148
149 $sLine = ltrim(SkipWord($sLine));
150 if ($sKey[0] >= "0" && $sKey[0] <= "9")
151 /* Revision number: delta or revision info */
152 $sRev = $sKey;
153 else
154 $fNewKey = 0;
155 continue;
156 }
157
158
159 /*
160 * Extract value
161 */
162 $fNoSemicolon = ($sKey == "desc" || $sKey == "log" || $sKey == "desc");
163 if ($fAt = ($sLine[0] == "@")) //check if the value is enclosed in '@'s
164 $sLine = substr($sLine, 1);
165 $asValue = array();
166 $fEnd = 0;
167 while (!$fEnd)
168 {
169 /* get new line? */
170 if (!$sLine || $sLine == "" || $sLine == "\n" || $sLine == "\r")
171 {
172 if (feof($hFile))
173 break;
174 /* Get next line and remove any EOF chars */
175 $iLine++;
176 $sLine = str_replace("\x1a", "", fgets($hFile, 0x1000));
177 continue;
178 }
179
180 //echo "debug line $iLine: $sLine";
181
182 /*
183 * Look for end char (either ; or @) and copy.
184 * If end of value then $sLine <- rest of line.
185 */
186 $fEnd = 0;
187 $cchLine = strlen($sLine);
188 if ($fAt)
189 { /* terminated with @ */
190 //$iAt = 0;
191 //for ($iAt; $iAt+1 < $cchLine; $iAt++)
192 // if ($sLine[$iAt] == '@' && ($fEnd = ($sLine[++$iAt] != '@')))
193 // break;
194 if ($sLine[0] == '@' && $sLine[1] != '@')
195 $fEnd = $iAt = 1;
196 else
197 {
198 $iAt = 0;
199 while ($iAt = strpos($sLine, "@", $iAt+1))
200 if ($fEnd = ($sLine[++$iAt] != '@'))
201 break;
202 }
203
204 if ($fEnd)
205 {
206 $asValue[] = str_replace("@@", "@", substr($sLine, 0, $iAt - 1));
207 /* if semicolon end, skip to it. ASSUMES: same line! */
208 if (!$fNoSemicolon && ($iAt = strpos($sLine, ";", $iAt)) >= 0)
209 $iAt++;
210 $sLine = (strlen($sLine) > $iAt && $iAt >= 0) ? substr($sLine, $iAt) : "";
211 }
212 else
213 {
214 $asValue[] = str_replace("@@", "@", $sLine);
215 $sLine = "";
216 }
217 }
218 else
219 { /* terminated with ';' */
220 $i = strpos($sLine, ';');
221 if ($fEnd = ($i > 0 || $sLine[0] == ';'))
222 {
223 //$asValue[] = str_replace("@@", "@", substr($sLine, 0, $i));
224 $asValue[] = substr($sLine, 0, $i);
225 $sLine = (strlen($sLine) > $i+1) ? substr($sLine, $i+1) : "";
226 }
227 else
228 {
229 //$asValue[] = str_replace("@@", "@", $sLine);
230 $asValue[] = $sLine;
231 $sLine = "";
232 }
233 }
234 }
235
236
237 /*
238 * Process the key.
239 */
240 switch ($sKey)
241 {
242 /*
243 * This is normally the keyword separating
244 * revision info from log+text info.
245 */
246 case "desc":
247 $fDesc = 1;
248 $sRev = "";
249 break;
250
251 /*
252 * Stop after the first log entry.
253 */
254 case "log":
255 $fStop = $fNoDeltas;
256 break;
257
258 /*
259 * Don'r read deltas for archives with the expand tag set
260 */
261 case "expand":
262 $fNoDeltas = 1;//= $asValue[0] != "";
263 break;
264 }
265
266 /*
267 * Save key and value in the appopriate place.
268 */
269 if ($sRev == "")
270 { /* Base keys */
271 if (sizeof($this->aaKeys) <= 0 //sanity check! head must come first and have a value!
272 && ($sKey != "head" || sizeof($asValue) <= 0 || $asValue[0] == ""))
273 {
274 $this->sError = "Invalid file format.";
275 fclose($hFile);
276 return 1;
277 }
278 $this->aasKeys[$sKey] = $asValue;
279 }
280 else if ($sKey != "text")
281 { /* Revision information keys */
282 if (!isset($this->aaasRevs[$sRev]))
283 $this->aaasRevs[$sRev] = array($sKey => $asValue);
284 else
285 $this->aaasRevs[$sRev][$sKey] = $asValue;
286 }
287 else
288 { /* Delta (ie. 'text') key */
289 $this->aasDeltas[$sRev] = $asValue;
290 }
291
292 /*
293 * Completed reading of this key, so next one.
294 */
295 $fNewKey = 1;
296
297 /* debug */
298 //echo "debug key: $sKey value(".sizeof($asValue)."):".$asValue[0]."\n";
299 }
300
301 fclose($hFile);
302
303 /*
304 * Return successfully.
305 */
306 $this->fOk = 1;
307
308 Odin32DBTimerStop($timer);
309 return 1;
310 }
311
312
313 /**
314 * Debug dump function.
315 */
316 function DumpInfo()
317 {
318 echo "\nDump:<br>\n";
319
320 while (list ($sKey, $asValue) = each ($this->aasKeys))
321 {
322 echo "* key: $sKey *<br>\n";
323 if (sizeof((array)$asValue) > 0)
324 {
325 while (list ($key, $s) = each ($asValue))
326 echo $s;
327 echo "<br>\n";
328 }
329 }
330
331 while (list ($sRev, $aasKeys) = each ($this->aaasRevs))
332 {
333 echo "* Revision: $sRev *<br>\n";
334 if (sizeof((array)$aasKeys) > 0)
335 {
336 while (list ($sKey, $asValue) = each ($aasKeys))
337 {
338 echo "* key: $sKey *<br>\n";
339 if (sizeof((array)$asValue) > 0)
340 {
341 while (list ($key, $s) = each ($asValue))
342 echo $s;
343 echo "<br>\n";
344 }
345 }
346 }
347 }
348
349 if (0)
350 {
351 while (list ($sKey, $asValue) = each ($this->aasDeltas))
352 {
353 echo "* delta for revision: $sKey *<br>\n";
354 if (sizeof((array)$asValue) > 0)
355 {
356 while (list ($key, $s) = each ($asValue))
357 echo $s."<br>";
358 echo "\n";
359 }
360 }
361 }
362 }
363
364
365 /**
366 * Prints the contents of the file to stdout.
367 *
368 * Color coding is enabled. (TODO)
369 *
370 * Currently only $sRevision == head revision is supported
371 * @returns Success indicator (true / false)
372 * @param $sRevision. Revision number. defaults to head revision.
373 *
374 */
375 function PrintRevision($sRevision)
376 {
377 /* defaults to head revision if empty */
378 if ($sRevision == "") $sRevision = $this->aasKeys["head"][0];
379 if (!isset($this->aasDeltas[$sRevision]))
380 {
381 $this->sError = "CVSFile::PrintRevision is called with an invalid revision number. ($sRevision)";
382 return 0;
383 }
384 /* to-be-removed - TODO - FIXME */
385 if ($sRevision != $this->aasKeys["head"][0])
386 {
387 $this->sError = "CVSFile::PrintRevision is called with an invalid revision number (not head).";
388 return 0;
389 }
390
391 /*
392 * Initiate the color encoder.
393 */
394 switch ($this->sExt)
395 {
396 case 'c':
397 case 'cpp':
398 case 'cxx':
399 case 'h':
400 case 'hpp':
401 C_ColorInit($aVariables);
402 break;
403 }
404
405
406
407 /*
408 * Write it!
409 */
410 echo "<table><tr><td bgcolor=#020286><pre><font size=-0 face=\"System VIO, System Monospaced\" color=#02FEFE>\n";
411
412 $fComment = 0;
413 $iLine = 0;
414 $cLines = sizeof($this->aasDeltas[$sRevision]);
415 //echo "<!-- debug $this->sExt -->\n";
416 while ($iLine < $cLines)
417 {
418 $sLine = htmlspecialchars($this->aasDeltas[$sRevision][$iLine++]);
419
420 /*
421 * Preprocessing... Color coding
422 */
423 switch ($this->sExt)
424 {
425 case 'c':
426 case 'cpp':
427 case 'cxx':
428 case 'h':
429 case 'hpp':
430 $sLine = C_ColorEncode($sLine, $aVariables);
431 //echo "<a name=$iLine>";
432 //C_ColorEncode2($sLine, $aVariables);
433 //echo "</a>";
434 break;
435
436 default:
437 echo "<a name=$iLine>$sLine</a>";
438
439 }
440
441 /*
442 * Finished processing of the line. So, write it.
443 */
444 echo "<a name=$iLine>$sLine</a>";
445 }
446
447 echo "</pre></td></tr></table>\n";
448
449 return 1;
450 }
451
452
453 /**
454 * Gets the revision number of the head revision.
455 * @returns head revision number
456 */
457 function getHead()
458 {
459 return $this->aasKeys["head"][0];
460 }
461
462
463 /**
464 * Gets the log string for the given revision.
465 * @returns Array of strings in the log text.
466 * @param $sRev Revision number to get log text for.
467 */
468 function getLog($sRev)
469 {
470 return @$this->aaasRevs[$sRev]["log"];
471 }
472
473
474 /**
475 * Gets the author for a revision.
476 * @return Author name.
477 * @param $sRev Revision number to get author name for.
478 */
479 function getAuthor($sRev)
480 {
481 return @$this->aaasRevs[$sRev]["author"][0];
482 }
483
484 /**
485 * Get date+time stap on a revision.
486 * @returns date string for the given revision.
487 * @param $sRev Revision number to get date+time for.
488 */
489 function getDate($sRev)
490 {
491 return @$this->aaasRevs[$sRev]["date"][0];
492 }
493
494 /**
495 * Get the age of the given revision.
496 * @returns Age string. (human readable)
497 * @param $sRev Revision number to get age for.
498 */
499 function getAge($sRev)
500 {
501 if (!isset($this->aaasRevs[$sRev]["date"][0]))
502 return "<i>error</i>";
503
504 $sDate = $this->aaasRevs[$sRev]["date"][0];
505 $sCurDate = date("Y.m.d.H.i.s");
506 if ($sDate > $sCurDate)
507 {
508 return "0 seconds"; //fixme?
509 }
510
511 /* seconds */
512 $i1 = substr($sCurDate, 17, 2);
513 $i2 = substr($sDate, 17, 2);
514 if ($fBorrow = ($i1 < $i2))
515 $i1 += 60;
516 $iSeconds = $i1 - $i2;
517
518 /* minuttes */
519 $i1 = substr($sCurDate, 14, 2);
520 $i2 = substr($sDate, 14, 2);
521 if ($fBorrow)
522 $i1--;
523 if ($fBorrow = ($i1 < $i2))
524 $i1 += 60;
525 $iMinuttes = $i1 - $i2;
526
527 /* hours */
528 $i1 = substr($sCurDate, 11, 2);
529 $i2 = substr($sDate, 11, 2);
530 if ($fBorrow)
531 $i1--;
532 if ($fBorrow = ($i1 < $i2))
533 $i1 += 24;
534 $iHours = $i1 - $i2;
535
536 /* days */
537 $i1 = substr($sCurDate, 8, 2);
538 $i2 = substr($sDate, 8, 2);
539 if ($fBorrow)
540 $i1--;
541 if ($fBorrow = ($i1 < $i2))
542 {
543 $iM = substr($sCurDate, 5, 2);
544 $iY = substr($sCurDate, 0, 4);
545 if ($iM == 1 || $iM == 3 || $iM == 5 || $iM == 7 || $iM == 8 || $iM == 10 || $iM == 12)
546 $i1 += 31;
547 else if ($iM == 4 || $iM == 6 || $iM == 9 || $iM == 11)
548 $i1 += 30;
549 else if (($iY % 4) != 0 || (($iY % 100) == 0 && ($iY % 1000) != 0))
550 $i1 += 28;
551 else
552 $i1 += 29;
553 }
554 $iDays = $i1 - $i2;
555
556 /* months */
557 $i1 = substr($sCurDate, 5, 2);
558 $i2 = substr($sDate, 5, 2);
559 if ($fBorrow)
560 $i1--;
561 if ($fBorrow = ($i1 < $i2))
562 $i1 += 12;
563 $iMonths = $i1 - $i2;
564
565 /* years */
566 $i1 = substr($sCurDate, 0, 4);
567 $i2 = substr($sDate, 0, 4);
568 if ($fBorrow)
569 $i1--;
570 $iYears = $i1 - $i2;
571
572 //printf("<!-- $sCurDate - $sDate = %04d.%02d.%02d.%02d.%02d.%02d -->\n", $iYears, $iMonths, $iDays, $iHours, $iMinuttes, $iSeconds);
573
574 /* make output */
575 if ($iYears > 0)
576 return "$iYears year".($iYears > 1 ? "s" : "")." $iMonths month".($iMonths > 1 ? "s" : "");
577 if ($iMonths > 0)
578 return "$iMonths month".($iMonths > 1 ? "s" : "")." $iDays day".($iDays > 1 ? "s" : "");
579 if ($iDays > 0)
580 return "$iDays day".($iDays > 1 ? "s" : "")." $iHours hour".($iHours > 1 ? "s" : "");
581 if ($iHours > 0)
582 return "$iHours hour".($iHours > 1 ? "s" : "")." $iMinuttes min";
583 if ($iMinuttes > 0)
584 return "$iMinuttes min $iSeconds sec";
585 return "$iSeconds seconds";
586 }
587
588}
589
590
591/**
592 * This function displayes the contents of an directory.
593 */
594function ListDirectory($sDir, $iSortColumn)
595{
596 global $sCVSROOT;
597
598 /*
599 * Validate and fixup $sDir.
600 * Note that relative .. is not allowed!
601 */
602 $sDir = str_replace("\\", "/", $sDir);
603 if ($sDir == "")
604 $sDir = ".";
605 if ($sDir[0] == '/')
606 $sDir = substr($sDir, 1);
607 if ($sDir[strlen($sDir)-1] == '/')
608 $sDir = substr($sDir, 0, strlen($sDir) - 1);
609 if ((strlen($sDir) == 2 && $sDir == "..")
610 ||
611 (substr($sDir, 0, 3) == "../")
612 ||
613 (substr($sDir, strlen($sDir)-3) == "/..")
614 ||
615 (strpos($sDir, "/../") > 0)
616 )
617 {
618 echo "<!-- Invalid parameter: \$sDir $sDir -->\n";
619 echo "<i>Invalid parameter: \$sDir $sDir </i>\n";
620 return 87;
621 }
622
623 /*
624 * Open the directory, read the contents into two arrays;
625 * one for files and one for directories. All files which
626 * don't end with ',v' are ignored.
627 */
628 $hDir = opendir($sCVSROOT.'/'.$sDir);
629 if (!$hDir)
630 {
631 echo "<!-- debug error opendir($sDir) failed -->\n";
632 echo "<i>debug error opendir($sDir) failed</i>\n";
633 return 5;
634 }
635
636 $asFiles = array();
637 $asSubDirs = array();
638 while ($sEntry = readdir($hDir))
639 {
640 if (is_dir($sCVSROOT.'/'.$sDir.'/'.$sEntry))
641 {
642 if ($sEntry != '..' && $sEntry != '.')
643 $asSubDirs[] = $sEntry;
644 }
645 else
646 {
647 $cchEntry = strlen($sEntry);
648 if ($cchEntry > 2 && substr($sEntry, $cchEntry - 2, 2) == ',v')
649 $asFiles[$sEntry] = $sEntry;
650 }
651 }
652 closedir($hDir);
653
654 /*
655 * Get CVS data.
656 */
657 $asRev = array();
658 $asAge = array();
659 $asAuthor = array();
660 $asLog = array();
661 for ($i = 0; list($sKey, $sFile) = each($asFiles); $i++)
662 {
663 $obj = new CVSFile($sDir.'/'.$sFile, 1);
664 if ($obj->fOk)
665 {
666 $asRev[$sFile] = $sRev = $obj->getHead();
667 $asAge[$sFile] = $obj->getAge($sRev);
668 $asAuthor[$sFile] = $obj->getAuthor($sRev);
669 $asLog[$sFile] = $obj->getLog($sRev);
670 }
671 else
672 $asLog[$sFile] = $obj->sError;
673 }
674
675 /*
676 * Sort the stuff.
677 */
678 sort($asSubDirs);
679 switch ($iSortColumn)
680 {
681 case 0: $asSorted = $asFiles; break;
682 case 1: $asSorted = $asRev; break;
683 case 2: $asSorted = $asAge; break;
684 case 3: $asSorted = $asAuthor; break;
685 case 4: $asSorted = $asLog; break;
686 default: $asSorted = $asFiles; break;
687 }
688 asort($asSorted);
689
690 /*
691 * Present data
692 */
693 $aColumnColors = array("#cccccc","#cccccc","#cccccc","#cccccc", "#88ff88","#cccccc","#cccccc","#cccccc","#cccccc");
694 echo "<table border=0 width=100% cellspacing=1 cellpadding=2>\n",
695 " <hr NOSHADE>\n",
696 " <th bgcolor=#".$aColumnColors[4+0-$iSortColumn]."><b><a href=cvs.phtml?sDir=$sDir&iSortColumn=0>Filename</a></b></th>\n",
697 " <th bgcolor=#".$aColumnColors[4+1-$iSortColumn]."><b><a href=cvs.phtml?sDir=$sDir&iSortColumn=1>Rev</a></b></th>\n",
698 " <th bgcolor=#".$aColumnColors[4+2-$iSortColumn]."><b><a href=cvs.phtml?sDir=$sDir&iSortColumn=2>Age</a></b></th>\n",
699 " <th bgcolor=#".$aColumnColors[4+3-$iSortColumn]."><b><a href=cvs.phtml?sDir=$sDir&iSortColumn=3>Author</a></b></th>\n",
700 " <th bgcolor=#".$aColumnColors[4+4-$iSortColumn]."><b><a href=cvs.phtml?sDir=$sDir&iSortColumn=4>Last Log Entry</a></b></th>\n",
701 " </hr>\n";
702 $i = 0;
703 /* directories */
704 if ($sDir != "." && $sDir != "")
705 {
706 if (($j = strrpos($sDir, '/')) > 0)
707 $sParentDir = substr($sDir, 0, $j - 1);
708 else
709 $sParentDir = "";
710 $sBgColor = ($i++ % 2) ? "" : " bgcolor=#ccccee";
711 echo " <tr>\n",
712 " <td", $sBgColor , ">",
713 "<font size=-1><a href=\"cvs.phtml?sDir=$sParentDir\">Parent Directory</a></font></td>\n",
714 " <td$sBgColor>&nbsp;</td>\n",
715 " <td$sBgColor>&nbsp;</td>\n",
716 " <td$sBgColor>&nbsp;</td>\n",
717 " <td$sBgColor>&nbsp;</td>\n",
718 " </tr>\n";
719 }
720 while (list($sKey, $sVal) = each($asSubDirs))
721 {
722 $sBgColor = ($i++ % 2) ? "" : " bgcolor=#ccccee";
723 echo " <tr>\n",
724 " <td$sBgColor><font size=-1><a href=\"cvs.phtml?sDir=$sDir/$sVal\">$sVal</a></font></td>\n",
725 " <td$sBgColor>&nbsp;</td>\n",
726 " <td$sBgColor>&nbsp;</td>\n",
727 " <td$sBgColor>&nbsp;</td>\n",
728 " <td$sBgColor>&nbsp;</td>\n",
729 " </tr>\n";
730 }
731
732 /* files */
733 while (list($sKey, $sVal) = each($asSorted))
734 {
735 $sBgColor = ($i++ % 2) ? "" : " bgcolor=#ccccee";
736 $sRev = isset($asRev[$sKey]) ? $asRev[$sKey] : "<i> error </i>";
737 $sAge = isset($asAge[$sKey]) ? $asAge[$sKey] : "<i> error </i>";
738 $sAuthor= isset($asAuthor[$sKey])?$asAuthor[$sKey] : "<i> error </i>";
739 for ($sLog = "", $j = sizeof($asLog[$sKey]) - 1; $j >= 0; $j--)
740 {
741 if ($sLog == "")
742 {
743 if (trim($asLog[$sKey][$j]) != "")
744 $sLog = $asLog[$sKey][$j];
745 continue;
746 }
747 $sLog = $asLog[$sKey][$j]."<br>".$sLog;
748 }
749 echo " <tr>\n",
750 " <td$sBgColor><font size=-1><a href=\"cvs.phtml?sFile=$sDir/$sKey\">$sKey</a></font></td>\n",
751 " <td$sBgColor><font size=-1><a href=\"cvs.phtml?sFile=$sDir/$sKey?sRev=$sRev\">$sRev</a></font></td>\n",
752 " <td$sBgColor><font size=-1>$sAge</font></td>\n",
753 " <td$sBgColor><font size=-1>$sAuthor</font></td>\n",
754 " <td$sBgColor><font size=-1>$sLog</font></td>\n",
755 " </tr>\n";
756 }
757
758 echo "</table>\n";
759
760
761 /*
762 * Debug dump.
763 *//*
764 while (list ($sKey, $sVal) = each ($asSubDirs))
765 echo "Dir: $sVal<br>\n";
766 while (list ($sKey, $sVal) = each ($asFiles))
767 echo "File: $sVal<br>\n";
768 */
769}
770
771
772/**
773 * Copies the first word.
774 * A words is: [a-zA-Z0-9_.]
775 *
776 * tested ok
777 * @returns Returns the word at the start of $s.
778 */
779function CopyWord($s)
780{
781 $cch = strlen($s);
782 for ($i = 0; $i < $cch; $i++)
783 {
784 $c = $s[$i];
785 if (!($c >= 'a' && $c <= 'z')
786 &&
787 !($c >= 'A' && $c <= 'Z')
788 &&
789 !($c >= '0' && $c <= '9')
790 &&
791 !($c == '.' || $c == '_')
792 )
793 break;
794 }
795 return substr($s, 0, $i);
796}
797
798
799/**
800 * Skips the first word.
801 * A words is: [a-zA-Z0-9_.]
802 *
803 * tested ok
804 * @returns $s - first word.
805 */
806function SkipWord($s)
807{
808 $cch = strlen($s);
809 for ($i = 0; $i < $cch; $i++)
810 {
811 $c = $s[$i];
812 if (!($c >= 'a' && $c <= 'z')
813 &&
814 !($c >= 'A' && $c <= 'Z')
815 &&
816 !($c >= '0' && $c <= '9')
817 &&
818 !($c == '.' || $c == '_')
819 )
820 break;
821 }
822 return substr($s, $i);
823}
824
825
826
827
828/*
829 * C color encoding.
830 */
831$aC_Keywords = array(
832// "auto" => 1,
833 "break" => 1,
834 "case" => 1,
835 "char" => 1,
836 "const" => 1,
837 "continue" => 1,
838 "default" => 1,
839// "defined" => 1,
840 "do" => 1,
841 "double" => 1,
842 "else" => 1,
843 "enum" => 1,
844 "extern" => 1,
845 "float" => 1,
846 "for" => 1,
847 "goto" => 1,
848 "if" => 1,
849 "int" => 1,
850 "long" => 1,
851 "register" => 1,
852 "return" => 1,
853 "short" => 1,
854 "sizeof" => 1,
855 "static" => 1,
856 "struct" => 1,
857 "switch" => 1,
858 "typedef" => 1,
859 "union" => 1,
860 "unsigned" => 1,
861 "void" => 1,
862 "while" => 1,
863 "class" => 1,
864 "delete" => 1,
865// "finally" => 1,
866 "friend" => 1,
867 "inline" => 1,
868 "new" => 1,
869 "operator" => 1,
870 "overload" => 1,
871 "private" => 1,
872 "protected" => 1,
873 "public" => 1,
874 "this" => 1,
875 "virtual" => 1,
876// "bool" => 1,
877// "true" => 1,
878// "false" => 1,
879 "explicit" => 1,
880 "mutable" => 1,
881 "typename" => 1,
882// "static_cast" => 1,
883// "const_cast" => 1,
884// "reinterpret_cast" => 1,
885// "dynamic_cast" => 1,
886// "using" => 1,
887 "typeid" => 1,
888// "asm" => 1,
889 "catch" => 1,
890 "signed" => 1,
891 "template" => 1,
892 "throw" => 1,
893 "try" => 1,
894// "namespace" => 1,
895 "volatile" => 1
896
897 );
898
899$aC_Symbols = array(
900 "{" => 1,
901 "}" => 1,
902// "[" => 1,
903// "]" => 1,
904// "(" => 1,
905// ")" => 1,
906// "." => 1,
907// "," => 1,
908 "!" => 1,
909 "%" => 1,
910// "&" => 1,
911 "&amp;" => 1,
912 "*" => 1,
913 "-" => 1,
914 "=" => 1,
915 "+" => 1,
916 ":" => 1,
917 ";" => 1,
918// "<" => 1,
919 "&lt;" => 1,
920// ">" => 1,
921 "&gt;" => 1,
922 "?" => 1,
923 "/" => 1,
924 "|" => 1,
925 "~" => 1,
926 "^" => 1,
927 "*" => 1);
928
929/**
930 * Initiate the variable array used by the C Color encoder.
931 * @param $aVaraibles Variable array. (output)
932 */
933function C_ColorInit(&$aVariables)
934{
935 global $aC_Keywords;
936 global $aC_Symbols;
937
938 $aVariables["fComment"] = 0;
939
940 ksort($aC_Keywords);
941 ksort($aC_Symbols);
942}
943
944
945/**
946 * Encode a line of C code.
947 * @param $sLine Line string to encode.
948 * @param $aVariables Variable array.
949 * @returns Color encoded line string.
950 */
951function C_ColorEncode($sLine, &$aVariables)
952{
953 global $aC_Keywords;
954 global $aC_Symbols;
955
956 $sRet = "";
957 $cchLine = strlen($sLine);
958
959 /*
960 * If mulitline comment we'll only check if it ends at this line.
961 * if it doesn't we'll do nothing.
962 * if it does we'll skip to then end of it.
963 */
964 if ($aVariables["fComment"])
965 {
966 if (!(($i = strpos($sLine, "*/")) || ($cchLine >= 2 && $sLine[0] == '*' && $sLine[1] == '/')))
967 return $sLine;
968 $i += 2;
969 $sRet = substr($sLine, 0, $i)."</font>";
970 $aVariables["fComment"] = 0;
971 }
972 else
973 $i = 0;
974
975 /*
976 * Loop thru the (remainings) of the line.
977 */
978 $fFirstNonBlank = 1;
979 while ($i < $cchLine)
980 {
981 $ch = $sLine[$i];
982 /* comment check */
983 if ($i+1 < $cchLine && $ch == '/')
984 {
985 if ($sLine[$i+1] == '/')
986 { /* one-line comment */
987 return $sRet . "<font color=#02FE02>" . substr($sLine, $i) . "</font>";
988 }
989
990 if ($sLine[$i+1] == '*')
991 { /* Start of multiline comment */
992 if ($j = strpos($sLine, "*/", $i + 2))
993 {
994 $sRet .= "<font color=#02FE02>" . substr($sLine, $i, $j+2 - $i) . "</font>";
995 $i = $j + 2;
996 }
997 else
998 {
999 $aVariables["fComment"] = 1;
1000 return $sRet . "<font color=#02FE02>" . substr($sLine, $i);
1001 }
1002 continue;
1003 }
1004 }
1005
1006 /*
1007 * Check for string.
1008 */
1009 if ((($fDbl = (/*$sLine[$i] == '"' ||*/ substr($sLine, $i, 6) == "&quot;")) || $sLine[$i] == "'")
1010 && ($i == 0 || $sLine[$i-1] != '\\'))
1011 { /* start of a string */
1012 $j = $i + 1;
1013 if ($fDbl)
1014 {
1015 /* if ($sLine[$i] == '"')
1016 while ($j < $cchLine && $sLine[$j] != '"')
1017 $j += ($sLine[$j] == '\\') ? 2 : 1;
1018 else */
1019 {
1020 while ($j < $cchLine && ($sLine[$j] != '&' || substr($sLine, $j, 6) != "&quot;"))
1021 $j += ($sLine[$j] == '\\') ? 2 : 1;
1022 if ($j < $cchLine)
1023 $j += 5;
1024 }
1025 }
1026 else
1027 while ($j < $cchLine && $sLine[$j] != "'")
1028 $j += ($sLine[$j] == '\\') ? 2 : 1;
1029 $j++;
1030 $sRet .= "<font color=#FEFE02>".substr($sLine, $i, $j - $i)."</font>";
1031 $i = $j;
1032 continue;
1033 }
1034
1035 /*
1036 * Check for preprocessor directive.
1037 */
1038 if ($fFirstNonBlank && $ch == "#")
1039 {
1040 $j = $i + 1;
1041 while ($j < $cchLine && ($sLine[$j] == ' ' || $sLine[$j] == '\t'))
1042 $j++;
1043 $j += C_WordLen($sLine, $cchLine, $j);
1044 $sRet .= "<font color=#CECECE>" . substr($sLine, $i, $j - $i) . "</font>";
1045 $i = $j;
1046 $fFirstNonBlank = 0;
1047 continue;
1048 }
1049
1050 /*
1051 * If non-blank, lets check if we're at the start of a word...
1052 */
1053 $fBlank = ($ch == ' ' || $ch == '\t'); //TODO more "blanks"?
1054 if ($fFirstNonBlank) $fFirstNonBlank = $fBlank;
1055 $cchWord = !$fBlank ? C_WordLen($sLine, $cchLine, $i) : 0;
1056
1057 if ($cchWord > 0)
1058 {
1059 /*
1060 * Check for keyword or number.
1061 */
1062 if ($cchWord > 0 && (isset($aC_Keywords[substr($sLine, $i, $cchWord)]) || ($ch >= '0' && $ch <= '9')))
1063 $sRet .= "<font color=#FF0202>" . substr($sLine, $i, $cchWord) . "</font>";
1064
1065 /*
1066 * Skip word.
1067 */
1068 else
1069 $sRet .= substr($sLine, $i, $cchWord);
1070 $i += $cchWord;
1071 continue;
1072 }
1073
1074
1075 /*
1076 * Prepare for symbol check. (we'll have to check for HTML stuff like &amp;).
1077 */
1078 $cchWord = 1;
1079 if ($ch == '&')
1080 {
1081 /*
1082 while ($cchWord < 8 && $sLine[$i+$cchWord] != ';' &&
1083 ( ($sLine[$i+$cchWord] >= 'a' && $sLine[$i+$cchWord] <= 'z')
1084 || ($sLine[$i+$cchWord] >= 'A' && $sLine[$i+$cchWord] <= 'Z')
1085 )
1086 )
1087 $cchWord++;
1088
1089 if ($sLine[$i + $cchWord++] != ';')
1090 $cchWord = 1;
1091 */
1092 if (substr($sLine, $i, 5) == "&amp;")
1093 $cchWord = 5;
1094 else if (substr($sLine, $i, 4) == "&gt;" || substr($sLine, $i, 4) == "&lt;")
1095 $cchWord = 4;
1096 }
1097
1098 /*
1099 * Check for Symbol.
1100 */
1101 if (isset($aC_Symbols[substr($sLine, $i, $cchWord)]))
1102 {
1103 $sRet .= "<font color=#CECECE>" . substr($sLine, $i, $cchWord) . "</font>";
1104 $i += $cchWord;
1105 continue;
1106 }
1107
1108
1109 /*
1110 * Copy char
1111 */
1112 $sRet .= $sLine[$i];
1113 $i++;
1114 }
1115
1116 return $sRet;
1117}
1118
1119
1120/**
1121 * Encode a line of C code.
1122 * @param $sLine Line string to encode.
1123 * @param $aVariables Variable array.
1124 * @returns Color encoded line string.
1125 */
1126function C_ColorEncode2($sLine, &$aVariables)
1127{
1128 global $aC_Keywords;
1129 global $aC_Symbols;
1130
1131 $cchLine = strlen($sLine);
1132
1133 /*
1134 * If mulitline comment we'll only check if it ends at this line.
1135 * if it doesn't we'll do nothing.
1136 * if it does we'll skip to then end of it.
1137 */
1138 if ($aVariables["fComment"])
1139 {
1140 if (!(($i = strpos($sLine, "*/")) || ($cchLine >= 2 && $sLine[0] == '*' && $sLine[1] == '/')))
1141 {
1142 echo $sLine;
1143 return;
1144 }
1145 $i += 2;
1146 echo substr($sLine, 0, $i)."</font>";
1147 $aVariables["fComment"] = 0;
1148 }
1149 else
1150 $i = 0;
1151
1152 /*
1153 * Loop thru the (remainings) of the line.
1154 */
1155 $fFirstNonBlank = 1;
1156 while ($i < $cchLine)
1157 {
1158 $ch = $sLine[$i];
1159 /* comment check */
1160 if ($i+1 < $cchLine && $ch == '/')
1161 {
1162 if ($sLine[$i+1] == '/')
1163 { /* one-line comment */
1164 echo "<font color=#02FE02>" . substr($sLine, $i) . "</font>";
1165 return;
1166 }
1167
1168 if ($sLine[$i+1] == '*')
1169 { /* Start of multiline comment */
1170 if ($j = strpos($sLine, "*/", $i + 2))
1171 {
1172 echo "<font color=#02FE02>" . substr($sLine, $i, $j+2 - $i) . "</font>";
1173 $i = $j + 2;
1174 }
1175 else
1176 {
1177 $aVariables["fComment"] = 1;
1178 echo "<font color=#02FE02>" . substr($sLine, $i);
1179 return;
1180 }
1181 continue;
1182 }
1183 }
1184
1185 /*
1186 * Check for string.
1187 */
1188 if ((($fDbl = (/*$sLine[$i] == '"' ||*/ substr($sLine, $i, 6) == "&quot;")) || $sLine[$i] == "'")
1189 && ($i == 0 || $sLine[$i-1] != '\\'))
1190 { /* start of a string */
1191 $j = $i + 1;
1192 if ($fDbl)
1193 {
1194 /* if ($sLine[$i] == '"')
1195 while ($j < $cchLine && $sLine[$j] != '"')
1196 $j += ($sLine[$j] == '\\') ? 2 : 1;
1197 else */
1198 {
1199 while ($j < $cchLine && ($sLine[$j] != '&' || substr($sLine, $j, 6) != "&quot;"))
1200 $j += ($sLine[$j] == '\\') ? 2 : 1;
1201 if ($j < $cchLine)
1202 $j += 5;
1203 }
1204 }
1205 else
1206 while ($j < $cchLine && $sLine[$j] != "'")
1207 $j += ($sLine[$j] == '\\') ? 2 : 1;
1208 $j++;
1209 echo "<font color=#FEFE02>".substr($sLine, $i, $j - $i)."</font>";
1210 $i = $j;
1211 continue;
1212 }
1213
1214 /*
1215 * Check for preprocessor directive.
1216 */
1217 if ($fFirstNonBlank && $ch == "#")
1218 {
1219 $j = $i + 1;
1220 while ($j < $cchLine && ($sLine[$j] == ' ' || $sLine[$j] == '\t'))
1221 $j++;
1222 $j += C_WordLen($sLine, $cchLine, $j);
1223 echo "<font color=#CECECE>" . substr($sLine, $i, $j - $i) . "</font>";
1224 $i = $j;
1225 $fFirstNonBlank = 0;
1226 continue;
1227 }
1228
1229 /*
1230 * If non-blank, lets check if we're at the start of a word...
1231 */
1232 $fBlank = ($ch == ' ' || $ch == '\t'); //TODO more "blanks"?
1233 if ($fFirstNonBlank) $fFirstNonBlank = $fBlank;
1234 $cchWord = !$fBlank ? C_WordLen($sLine, $cchLine, $i) : 0;
1235
1236 if ($cchWord > 0)
1237 {
1238 /*
1239 * Check for keyword or number.
1240 */
1241 if ($cchWord > 0 && (isset($aC_Keywords[substr($sLine, $i, $cchWord)]) || ($ch >= '0' && $ch <= '9')))
1242 echo "<font color=#FF0202>" . substr($sLine, $i, $cchWord) . "</font>";
1243
1244 /*
1245 * Skip word.
1246 */
1247 else
1248 echo substr($sLine, $i, $cchWord);
1249 $i += $cchWord;
1250 continue;
1251 }
1252
1253
1254 /*
1255 * Prepare for symbol check. (we'll have to check for HTML stuff like &amp;).
1256 */
1257 $cchWord = 1;
1258 if ($ch == '&')
1259 {
1260 /*
1261 while ($cchWord < 8 && $sLine[$i+$cchWord] != ';' &&
1262 ( ($sLine[$i+$cchWord] >= 'a' && $sLine[$i+$cchWord] <= 'z')
1263 || ($sLine[$i+$cchWord] >= 'A' && $sLine[$i+$cchWord] <= 'Z')
1264 )
1265 )
1266 $cchWord++;
1267
1268 if ($sLine[$i + $cchWord++] != ';')
1269 $cchWord = 1;
1270 */
1271 if (substr($sLine, $i, 5) == "&amp;")
1272 $cchWord = 5;
1273 else if (substr($sLine, $i, 4) == "&gt;" || substr($sLine, $i, 4) == "&lt;")
1274 $cchWord = 4;
1275 }
1276
1277 /*
1278 * Check for Symbol.
1279 */
1280 if (isset($aC_Symbols[substr($sLine, $i, $cchWord)]))
1281 {
1282 echo "<font color=#CECECE>" . substr($sLine, $i, $cchWord) . "</font>";
1283 $i += $cchWord;
1284 continue;
1285 }
1286
1287
1288 /*
1289 * Copy char
1290 */
1291 echo $ch;
1292 $i++;
1293 }
1294
1295 return;
1296}
1297
1298
1299/**
1300 * Calculates the lenght of the word which eventually starts at [$i].
1301 * @param $sLine Line.
1302 * @param $cchLine Line length.
1303 * @param $i Line index.
1304 * @returns Word length.
1305 */
1306function C_WordLen($sLine, $cchLine, $i)
1307{
1308
1309 /*
1310 * Check that previous letter wasen't a possible
1311 * word part.
1312 */
1313 if ($i > 0)
1314 {
1315 $ch = $sLine[$i - 1];
1316 if ( ($ch >= 'a' && $ch <= 'z')
1317 || ($ch >= 'A' && $ch <= 'Z')
1318 || ($ch >= '0' && $ch <= '9')
1319 || ($ch == '_')
1320 || ($ch == '$')
1321 )
1322 return 0;
1323 }
1324
1325 /*
1326 * Count letters in the word
1327 */
1328 $j = $i;
1329 $ch = $sLine[$i];
1330 while ($i < $cchLine &&
1331 ( ($ch >= 'a' && $ch <= 'z')
1332 || ($ch >= 'A' && $ch <= 'Z')
1333 || ($ch >= '0' && $ch <= '9')
1334 || ($ch == '_')
1335 || ($ch == '$')
1336 )
1337 )
1338 $ch = @$sLine[++$i];
1339 return $i - $j;
1340}
1341
1342?>
1343
Note: See TracBrowser for help on using the repository browser.