Develop and Download Open Source Software

Browse Subversion Repository

Contents of /WebModuleUnit1.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations) (download) (as text)
Sun Sep 25 06:49:06 2016 UTC (7 years, 6 months ago) by yamat0jp
File MIME type: text/x-pascal
File size: 20590 byte(s)
Error occurred while calculating annotation data.
html5+css3 でindex.htmを記述してみました
1 unit WebModuleUnit1;
2
3
4 interface
5
6 uses System.SysUtils, System.Classes, Web.HTTPApp, FireDAC.Stan.Intf,
7 FireDAC.Stan.Option, FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS,
8 FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt,
9 FireDAC.UI.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Phys,
10 FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs, Data.DB,
11 FireDAC.Comp.Client, FireDAC.Comp.DataSet, Web.HTTPProd, Web.DSProd,
12 AnsiStrings, System.DateUtils, System.Types, Vcl.AppEvnts, System.NetEncoding;
13
14 type
15 TWebModule1 = class(TWebModule)
16 FDTable1: TFDTable;
17 FDConnection1: TFDConnection;
18 FDTable2: TFDTable;
19 FDTable2home: TWideMemoField;
20 FDTable2title: TWideMemoField;
21 FDTable2title2: TWideMemoField;
22 FDTable2pass: TWideMemoField;
23 PageProducer1: TPageProducer;
24 DataSetPageProducer2: TDataSetPageProducer;
25 FDTable1name: TWideMemoField;
26 FDTable1no: TIntegerField;
27 FDTable1date: TWideMemoField;
28 FDTable1sub: TWideMemoField;
29 FDTable1com: TWideMemoField;
30 FDTable1pass: TWideMemoField;
31 adminDS: TDataSetPageProducer;
32 FDTable2ngwords: TWideMemoField;
33 FDTable3: TFDTable;
34 FDTable3link: TIntegerField;
35 FDTable3count: TIntegerField;
36 FDTable1line: TIntegerField;
37 FDTable3line: TIntegerField;
38 FDTable2mente: TBooleanField;
39 procedure WebModule1DefaultHandlerAction(Sender: TObject;
40 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
41 procedure PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
42 const TagString: string; TagParams: TStrings; var ReplaceText: string);
43 procedure WebModule1registAction(Sender: TObject; Request: TWebRequest;
44 Response: TWebResponse; var Handled: Boolean);
45 procedure DataSetPageProducer2HTMLTag(Sender: TObject; Tag: TTag;
46 const TagString: string; TagParams: TStrings; var ReplaceText: string);
47 procedure WebModule1userdelAction(Sender: TObject; Request: TWebRequest;
48 Response: TWebResponse; var Handled: Boolean);
49 procedure WebModule1adminAction(Sender: TObject; Request: TWebRequest;
50 Response: TWebResponse; var Handled: Boolean);
51 procedure WebModule1admindelAction(Sender: TObject; Request: TWebRequest;
52 Response: TWebResponse; var Handled: Boolean);
53 procedure WebModule1loginAction(Sender: TObject; Request: TWebRequest;
54 Response: TWebResponse; var Handled: Boolean);
55 procedure WebModuleBeforeDispatch(Sender: TObject; Request: TWebRequest;
56 Response: TWebResponse; var Handled: Boolean);
57 procedure WebModule1setupAction(Sender: TObject; Request: TWebRequest;
58 Response: TWebResponse; var Handled: Boolean);
59 procedure WebModule1searchAction(Sender: TObject; Request: TWebRequest;
60 Response: TWebResponse; var Handled: Boolean);
61 procedure WebModuleCreate(Sender: TObject);
62 procedure WebModuleDestroy(Sender: TObject);
63 procedure WebModule1adminsetAction(Sender: TObject; Request: TWebRequest;
64 Response: TWebResponse; var Handled: Boolean);
65 procedure WebModule1cssAction(Sender: TObject; Request: TWebRequest;
66 Response: TWebResponse; var Handled: Boolean);
67 procedure WebModuleAfterDispatch(Sender: TObject; Request: TWebRequest;
68 Response: TWebResponse; var Handled: Boolean);
69 private
70 { private ���� }
71 public
72 { public ���� }
73 user: string;
74 time: Int64;
75 words: TStringList;
76 position: integer;
77 uri: string;
78 er: string;
79 foo: string;
80 function footer(const path: string): string;
81 procedure regist(var com: string);
82 end;
83
84 var
85 WebModuleClass: TComponentClass = TWebModule1;
86
87 implementation
88
89 { %CLASSGROUP 'Vcl.Controls.TControl' }
90
91 {$R *.dfm}
92
93 procedure TWebModule1.DataSetPageProducer2HTMLTag(Sender: TObject; Tag: TTag;
94 const TagString: string; TagParams: TStrings; var ReplaceText: string);
95 begin
96 ReplaceText := FDTable1.FieldByName(TagString).AsString;
97 if TagString = 'com' then
98 regist(ReplaceText);
99 end;
100
101 function TWebModule1.footer(const path: string): string;
102 var
103 s1, s2, t1, t2: string;
104 home: string;
105 i, k, count: integer;
106 function linkcontent: string;
107 var
108 j, link: integer;
109 begin
110 result := '';
111 link := FDTable3.FieldByName('link').AsInteger;
112 if position > link div 2 then
113 begin
114 if (FDTable1.RecordCount - 1) div count < position + link div 2 then
115 i := FDTable1.RecordCount div count - link - position
116 else
117 i := -(link div 2)
118 end
119 else if position = -1 then
120 i := -position + FDTable1.RecordCount div count - link
121 else
122 i := -position;
123 for j := 0 to link do
124 begin
125 if FDTable1.RecordCount <= (position + i + j) * count then
126 break;
127 if position + i + j < 0 then
128 continue;
129 if i + j = 0 then
130 result := result + ' ' + IntToStr(position + 1) + ' '
131 else
132 result := result + Format(' <a href="' + home + path +
133 '?pos=%d#article">%d</a> ',
134 [position + i + j, position + 1 + i + j]);
135 end;
136 end;
137
138 begin
139 count := FDTable3.FieldByName('count').AsInteger;
140 home := FDTable2.FieldByName('home').AsString;
141 if position <= -1 then
142 begin
143 s1 := '<nav>���V%d�����L�����\��<br><center>Pages : [<b>';
144 s2 := '<<' + linkcontent + '>></b>] <b>���V</b><br></center></nav>';
145 result := Format(s1, [count]) + s2;
146 end
147 else
148 begin
149 if position = 0 then
150 t1 := '?pos=0'
151 else
152 t1 := '?pos=' + IntToStr(position - 1);
153 i := (FDTable1.RecordCount - 1) div count;
154 if position > i then
155 position := i;
156 if position = i then
157 begin
158 t2 := '?pos=' + position.ToString + '#article';
159 k := FDTable1.RecordCount;
160 end
161 else
162 begin
163 t2 := '?pos=' + IntToStr(position + 1) + '#article';
164 k := (position + 1) * count;
165 end;
166 s1 := '<nav>%d ���� %d ������ %d �������\��<br><center>Page : [<b>';
167 s2 := '<a href="' + home + path + t1 + '#article"><<</a>' + linkcontent +
168 '<a href="' + home + path + t2 + '">>></a></b>] <b><a href="' + home + path +
169 '#article">���V</a></b></center></nav>';
170 result := Format(s1, [FDTable1.RecordCount, position * count + 1, k]) + s2;
171 end;
172 end;
173
174 procedure TWebModule1.PageProducer1HTMLTag(Sender: TObject; Tag: TTag;
175 const TagString: string; TagParams: TStrings; var ReplaceText: string);
176 var
177 i, j, count: integer;
178 s: TDataSetPageProducer;
179 begin
180 if TagString = 'home' then
181 ReplaceText := FDTable2.FieldByName('home').AsString;
182 if (TagString = 'title') or (TagString = 'title2') then
183 ReplaceText := FDTable2.FieldByName(TagString).AsString;
184 if TagString = 'username' then
185 ReplaceText := user;
186 if TagString = 'main' then
187 begin
188 if FDTable1.RecordCount = 0 then
189 begin
190 if uri = '/index' then
191 ReplaceText := '<hr>�������e������������.<hr>';
192 end
193 else
194 begin
195 count := FDTable3.FieldByName('count').AsInteger;
196 if uri = '/admin' then
197 s := adminDS
198 else
199 s := DataSetPageProducer2;
200 if position < -1 then
201 position := -1;
202 if (position + 1) * count > FDTable1.RecordCount then
203 position := (FDTable1.RecordCount - 1) div count;
204 if position = -1 then
205 begin
206 if FDTable1.RecordCount < count then
207 j := FDTable1.RecordCount mod count
208 else
209 j := count;
210 end
211 else if FDTable1.RecordCount < (position + 1) * count then
212 j := FDTable1.RecordCount - position * count
213 else
214 j := count;
215 if position = -1 then
216 FDTable1.Last
217 else
218 FDTable1.RecNo := (position + 1) * count;
219 for i := 1 to j do
220 begin
221 ReplaceText := ReplaceText + s.Content;
222 FDTable1.Prior;
223 end;
224 ReplaceText := '<article>' + ReplaceText + '</article>' + '<hr>';
225 end;
226 end;
227 if TagString = 'footer' then
228 if foo <> '' then
229 ReplaceText := foo
230 else
231 begin
232 foo := footer(uri);
233 ReplaceText := foo;
234 end;
235 if TagString = 'text' then
236 if FDTable1.Filtered = false then
237 ReplaceText := '����������'
238 else
239 ReplaceText := '�Y������ ' + IntToStr(FDTable1.RecordCount) + ' ��' +
240 '<br><#main>';
241 if TagString = 'pass' then
242 ReplaceText := FDTable2.FieldByName('pass').AsString;
243 if TagString = 'content' then
244 ReplaceText := er;
245 if (TagString = 'mente') and (FDTable2.FieldByName('mente').AsBoolean = True)
246 then
247 ReplaceText := 'checked="checked"';
248 end;
249
250 procedure TWebModule1.regist(var com: string);
251 var
252 i: integer;
253 begin
254 i := 1;
255 while True do
256 begin
257 i := Pos(#$D#$A, com, i);
258 if i = 0 then
259 break;
260 Delete(com, i, Length(#$D#$A));
261 Insert('<br>', com, i);
262 inc(i, 4);
263 end;
264 end;
265
266 procedure TWebModule1.WebModule1adminAction(Sender: TObject;
267 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
268 var
269 t: string;
270 x: Boolean;
271 procedure something;
272 var
273 s: TResourceStream;
274 begin
275 x := false;
276 s := TResourceStream.Create(HInstance, 'admin', RT_RCDATA);
277 try
278 uri := '/admin';
279 Response.ContentType := 'text/html; charset=utf-8;';
280 Response.Content := PageProducer1.ContentFromStream(s)
281 finally
282 s.Free;
283 end;
284 end;
285 procedure addcookie(day: integer; pass: string);
286 begin
287 with Response.Cookies.Add do
288 begin
289 path := '/';
290 Expires := Now + day;
291 Name := 'psw';
292 Value := AnsiString(pass);
293 end;
294 end;
295
296 begin
297 if Request.Query = 'del' then
298 begin
299 addcookie(-3, '');
300 Response.SendRedirect(FDTable2.FieldByName('home').AsAnsiString + '/index');
301 Exit;
302 end;
303 x := True;
304 t := Request.ContentFields.Values['password'];
305 position := StrToIntDef(Request.QueryFields.Values['pos'], -1);
306 if t <> '' then
307 begin
308 addcookie(14, t);
309 if t = FDTable2.FieldByName('pass').AsString then
310 something;
311 end
312 else if Request.CookieFields.Values['psw'] = FDTable2.FieldByName('pass').AsString
313 then
314 something;
315 if x = True then
316 Response.SendRedirect(FDTable2.FieldByName('home').AsAnsiString + '/login');
317 end;
318
319 procedure TWebModule1.WebModule1admindelAction(Sender: TObject;
320 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
321 var
322 i: integer;
323 begin
324 for i := 0 to Request.ContentFields.count - 1 do
325 if FDTable1.Locate('no', Request.ContentFields.ValueFromIndex[i], []) = True
326 then
327 FDTable1.Delete;
328 Response.SendRedirect(FDTable2.FieldByName('home').AsAnsiString + '/admin');
329 end;
330
331 procedure TWebModule1.WebModule1adminsetAction(Sender: TObject;
332 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
333 var
334 s: string;
335 x: Boolean;
336 begin
337 s := Request.ContentFields.Values['pass'];
338 if FDTable2.FieldByName('pass').AsString <> s then
339 begin
340 FDTable2.Edit;
341 FDTable2.FieldByName('pass').AsString := s;
342 FDTable2.Post;
343 with Response.Cookies.Add do
344 begin
345 path := AnsiString(FDTable2.FieldByName('home').AsAnsiString + '/admin');
346 Expires := Now + 14;
347 Name := 'psw';
348 Value := AnsiString(s);
349 end;
350 end;
351 x := Request.ContentFields.Values['mente'] = 'on';
352 if FDTable2.FieldByName('mente').AsBoolean <> x then
353 begin
354 FDTable2.Edit;
355 FDTable2.FieldByName('mente').AsBoolean := x;
356 FDTable2.Post;
357 end;
358 Response.SendRedirect(FDTable2.FieldByName('home').AsAnsiString + '/admin');
359 end;
360
361 procedure TWebModule1.WebModule1cssAction(Sender: TObject; Request: TWebRequest;
362 Response: TWebResponse; var Handled: Boolean);
363 var
364 s: string;
365 begin
366 s := Request.QueryFields.Values['css'];
367 if (s = 'main') or (s = 'pc') or (s = 'smart') or (s = 'tablet') then
368 begin
369 Response.ContentType := 'text/css';
370 Response.ContentStream := TResourceStream.Create(HInstance, s, RT_RCDATA);
371 end;
372 end;
373
374 procedure TWebModule1.WebModule1DefaultHandlerAction(Sender: TObject;
375 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
376 var
377 s: TResourceStream;
378 t: TURLEncoding;
379 begin
380 if FDTable2.FieldByName('mente').AsBoolean = True then
381 begin
382 s := TResourceStream.Create(HInstance, 'mente', RT_RCDATA);
383 try
384 uri := '/mente';
385 Response.ContentType := 'text/html; charset=utf-8;';
386 Response.Content := PageProducer1.ContentFromStream(s);
387 finally
388 s.Free;
389 end;
390 Exit;
391 end;
392 position := StrToIntDef(Request.QueryFields.Values['pos'], -1);
393 s := TResourceStream.Create(HInstance, 'index', RT_RCDATA);
394 t := TURLEncoding.Create;
395 try
396 user := t.Decode(Request.CookieFields.Values['UID']);
397 uri := '/index';
398 Response.ContentType := 'text/html; charset=utf-8;';
399 Response.Content := PageProducer1.ContentFromStream(s);
400 finally
401 s.Free;
402 end;
403 end;
404
405 procedure TWebModule1.WebModule1loginAction(Sender: TObject;
406 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
407 var
408 s: TResourceStream;
409 begin
410 s := TResourceStream.Create(HInstance, 'login', RT_RCDATA);
411 try
412 uri := '/login';
413 Response.ContentType := 'text/html; charset=utf-8;';
414 Response.Content := PageProducer1.ContentFromStream(s);
415 finally
416 s.Free;
417 end;
418 end;
419
420 procedure TWebModule1.WebModule1registAction(Sender: TObject;
421 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
422 var
423 na, sub, com, pass: string;
424 no, line: integer;
425 i: integer;
426 s: TResourceStream;
427 t: TURLEncoding;
428 begin
429 with Request.ContentFields do
430 begin
431 na := Values['name'];
432 sub := Values['title'];
433 com := Values['comment'];
434 pass := Values['password'];
435 end;
436 er := '';
437 line := 0;
438 if na = '' then
439 na := '�N������';
440 if sub = '' then
441 sub := '�^�C�g������';
442 if com = '' then
443 er := '�{��������������.'#$D#$A
444 else
445 for i := 1 to Length(com) do
446 if Copy(com, i, i + 2) = #$D#$A then
447 inc(line);
448 for i := 0 to words.count - 1 do
449 if ContainsText(AnsiString(com), AnsiString(words[i])) = True then
450 begin
451 er := er + '���~����������������.';
452 break;
453 end;
454 if FDTable1.RecordCount = 0 then
455 no := 1
456 else
457 begin
458 FDTable1.Last;
459 no := FDTable1.FieldByName('no').AsInteger + 1;
460 if SecondsBetween(Now, StrToDateTime(FDTable1.FieldByName('date').AsString))
461 < time then
462 er := '����������������.';
463 end;
464 if er <> '' then
465 begin
466 Response.ContentType := 'text/html; charset=utf-8;';
467 s := TResourceStream.Create(HInstance, 'regist', RT_RCDATA);
468 try
469 Response.Content := PageProducer1.ContentFromStream(s);
470 finally
471 s.Free;
472 end;
473 Exit;
474 end;
475 t := TURLEncoding.Create;
476 try
477 FDTable1.AppendRecord([na, no, DateTimeToStr(Now), sub,
478 ReplaceText(ReplaceText(com, '<', t.Encode('<')), '>', t.Encode('>')),
479 pass, line]);
480 finally
481 t.Free;
482 end;
483 with Response.Cookies.Add do
484 begin
485 path := '/';
486 Name := 'UID';
487 Value := AnsiString(na);
488 Expires := Now + 1;
489 end;
490 Response.SendRedirect(FDTable2.FieldByName('home').AsAnsiString +
491 '/index#article');
492 end;
493
494 procedure TWebModule1.WebModule1searchAction(Sender: TObject;
495 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
496 var
497 s: TStringList;
498 t1, t2, t3: string;
499 i, j: integer;
500 m: TResourceStream;
501 begin
502 t1 := Request.ContentFields.Values['filter'];
503 t3 := '';
504 s := TStringList.Create;
505 try
506 s.DelimitedText := Request.ContentFields.Values['word1'];
507 for i := 0 to s.count - 1 do
508 begin
509 t2 := Trim(s[i]);
510 if t2 = '' then
511 continue;
512 if t3 <> '' then
513 t3 := t3 + ' and ';
514 t3 := t3 + t1 + ' LIKE ''%' + t2 + '%''';
515 end;
516 finally
517 s.Free;
518 end;
519 if t3 = '' then
520 begin
521 m := TResourceStream.Create(HInstance, 'search', RT_RCDATA);
522 try
523 Response.ContentType := 'text/html; charset=utf-8;';
524 Response.Content := PageProducer1.ContentFromStream(m);
525 finally
526 m.Free;
527 end;
528 Exit;
529 end;
530 FDTable1.Filter := t3;
531 FDTable1.Filtered := True;
532 m := TResourceStream.Create(HInstance, 'search', RT_RCDATA);
533 try
534 j := 0;
535 for i := 1 to FDTable1.RecordCount - 1 do
536 begin
537 inc(j, FDTable1.FieldByName('line').AsInteger);
538 FDTable1.Next;
539 end;
540 PageProducer1.HTMLDoc.LoadFromStream(m);
541 Response.ContentType := 'text/html; charset=utf-8;';
542 if (t3 <> '') and (j > FDTable3.FieldByName('line').AsInteger) then
543 begin
544 t1 := PageProducer1.Content;
545 i := Pos('<#main>', t1);
546 Delete(t1, i, Length('<#main>'));
547 Response.Content := t1 + Format('�\���s����%d�s��������������.',
548 [FDTable3.FieldByName('line').AsInteger]);
549 end
550 else
551 Response.Content := PageProducer1.ContentFromString
552 (PageProducer1.Content);
553 finally
554 FDTable1.Filtered := false;
555 m.Free;
556 end;
557 end;
558
559 procedure TWebModule1.WebModule1setupAction(Sender: TObject;
560 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
561 var
562 i: integer;
563 s: string;
564 begin
565 FDTable2.Edit;
566 for i := 0 to Request.ContentFields.count - 1 do
567 begin
568 s := Request.ContentFields.Names[i];
569 FDTable2.FieldByName(s).AsString := Request.ContentFields.ValueFromIndex[i]
570 end;
571 FDTable2.Post;
572 Handled := false;
573 end;
574
575 procedure TWebModule1.WebModule1userdelAction(Sender: TObject;
576 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
577 var
578 s: string;
579 i: integer;
580 begin
581 i := StrToIntDef(Request.ContentFields.Values['number'], 0);
582 if (i > 0) and (FDTable1.Locate('no', i, []) = True) then
583 begin
584 s := FDTable1.FieldByName('pass').AsString;
585 if (s <> '') and (s = Request.ContentFields.Values['password']) then
586 FDTable1.Delete;
587 end;
588 Handled := false;
589 end;
590
591 procedure TWebModule1.WebModuleAfterDispatch(Sender: TObject;
592 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
593 begin
594 foo := '';
595 end;
596
597 procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject;
598 Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
599 var
600 m: TResourceStream;
601 begin
602 if FDTable1.Exists = false then
603 FDTable1.CreateTable(false, [tpTable]);
604 if FDTable2.Exists = false then
605 begin
606 FDTable2.CreateTable(false, [tpTable]);
607 FDTable2.Active := True;
608 {
609 if (Request.ServerPort = 80) or (Request.ServerPort = 443) then
610 s := 'http://' + String(Request.Host)
611 else
612 s := 'http://' + String(Request.Host) + ':' +
613 IntToStr(Request.ServerPort);
614 }
615 FDTable2.AppendRecord([Request.ScriptName, 'pbbs clone',
616 '<center><font size=5 face=Verdana color=gray><b>P-BBS CLONE</b></font></center>',
617 'admin', '����,����,����', false]);
618 m := TResourceStream.Create(HInstance, 'setup', RT_RCDATA);
619 try
620 uri := '/setup';
621 Response.ContentType := 'text/html; charset=utf-8;';
622 Response.Content := PageProducer1.ContentFromStream(m);
623 finally
624 m.Free;
625 end;
626 Handled := True;
627 end
628 else
629 FDTable2.Active := True;
630 if FDTable3.Exists = false then
631 begin
632 FDTable3.CreateTable(false, [tpTable]);
633 FDTable3.Active := True;
634 FDTable3.AppendRecord([5, 20, 500]);
635 end
636 else
637 FDTable3.Active := True;
638 words.DelimitedText := FDTable2.FieldByName('ngwords').AsString;
639 FDTable1.Active := True;
640 {
641 t:='';
642 ssl:=TStringList.Create;
643 try
644 ssl.Add('/login');
645 ssl.Add('/admin');
646 if (ssl.IndexOf(Request.PathInfo) > -1)and(StartsText('https',FDTable2.FieldByName('home').AsString) = false) then
647 begin
648 s:=FDTable2.FieldByName('home').AsAnsiString;
649 Delete(s,Length(s),1);
650 t:='https'+Copy(s,5,Length(s))+Request.PathInfo;
651 end;
652 finally
653 ssl.Free;
654 end;
655 if t <> '' then
656 begin
657 Response.SendRedirect(t);
658 Exit;
659 end;
660 }
661 end;
662
663 procedure TWebModule1.WebModuleCreate(Sender: TObject);
664 begin
665 FDConnection1.Open('Database=data.sdb;LockingMode=Normal;DriverID=SQLite');
666 time := 1;
667 words := TStringList.Create;
668 end;
669
670 procedure TWebModule1.WebModuleDestroy(Sender: TObject);
671 begin
672 words.Free;
673 end;
674
675 end.
676

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26