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

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

More coding...

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