1 | <?php
|
---|
2 |
|
---|
3 | require "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 | */
|
---|
15 | class 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 | */
|
---|
800 | function 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> </td>\n",
|
---|
937 | " <td$sBgColor> </td>\n",
|
---|
938 | " <td$sBgColor> </td>\n",
|
---|
939 | " <td$sBgColor> </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> </td>\n",
|
---|
948 | " <td$sBgColor> </td>\n",
|
---|
949 | " <td$sBgColor> </td>\n",
|
---|
950 | " <td$sBgColor> </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 | */
|
---|
993 | function 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 | */
|
---|
1020 | function 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 | "&" => 1,
|
---|
1126 | "*" => 1,
|
---|
1127 | "-" => 1,
|
---|
1128 | "=" => 1,
|
---|
1129 | "+" => 1,
|
---|
1130 | ":" => 1,
|
---|
1131 | ";" => 1,
|
---|
1132 | // "<" => 1,
|
---|
1133 | "<" => 1,
|
---|
1134 | // ">" => 1,
|
---|
1135 | ">" => 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 | */
|
---|
1147 | function 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 | */
|
---|
1165 | function 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) == """)) || $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) != """))
|
---|
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 &).
|
---|
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) == "&")
|
---|
1307 | $cchWord = 5;
|
---|
1308 | else if (substr($sLine, $i, 4) == ">" || substr($sLine, $i, 4) == "<")
|
---|
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 | */
|
---|
1340 | function 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) == """)) || $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) != """))
|
---|
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 &).
|
---|
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) == "&")
|
---|
1486 | $cchWord = 5;
|
---|
1487 | else if (substr($sLine, $i, 4) == ">" || substr($sLine, $i, 4) == "<")
|
---|
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 | */
|
---|
1520 | function 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 |
|
---|