Subversion Repositories fastphp

Rev

Rev 33 | Rev 45 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit FastPHPUtils;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, SysUtils, StrUtils, Dialogs, IniFiles, Classes, Forms;
  7.  
  8. const
  9.   FASTPHP_GOTO_URI_PREFIX = 'fastphp://editor/gotoline/';
  10.  
  11. function FastPHPConfig: TMemIniFile;
  12. function GetPHPExe: string;
  13. function RunPHPScript(APHPFileName: string; lint: boolean=false): string;
  14. function ParseCHM(const chmFile: TFileName): boolean;
  15. function IsValidPHPExe(const exeFile: TFileName): boolean;
  16.  
  17. implementation
  18.  
  19. uses
  20.   Functions;
  21.  
  22. var
  23.   __FastPHPConfig: TMemIniFile;
  24.  
  25. function FastPHPConfig: TMemIniFile;
  26. begin
  27.   if not Assigned(__FastPHPConfig) then
  28.   begin
  29.     __FastPHPConfig := TMemIniFile.Create(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'FastPHP.ini');
  30.   end;
  31.   result := __FastPHPConfig;
  32. end;
  33.  
  34. function GetPHPExe: string;
  35. var
  36.   od: TOpenDialog;
  37. begin
  38.   result := FastPHPConfig.ReadString('Paths', 'PHPInterpreter', '');
  39.   if not FileExists(result) then
  40.   begin
  41.     od := TOpenDialog.Create(nil);
  42.     try
  43.       od.DefaultExt := '.exe';
  44.       od.FileName := 'php.exe';
  45.       od.Filter := 'Executable file (*.exe)|*.exe';
  46.       od.Options := [ofReadOnly, ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing];
  47.       od.Title := 'Please chose your PHP interpreter (php.exe)';
  48.  
  49.       if not od.Execute then exit;
  50.       if not FileExists(od.FileName) then exit;
  51.       result := od.FileName;
  52.     finally
  53.       od.Free;
  54.     end;
  55.  
  56.     if not IsValidPHPExe(result) then
  57.     begin
  58.       ShowMessage('This is not a valid PHP executable.');
  59.       exit;
  60.     end;
  61.  
  62.     FastPHPConfig.WriteString('Paths', 'PHPInterpreter', result);
  63.     FastPHPConfig.UpdateFile;
  64.   end;
  65. end;
  66.  
  67. function RunPHPScript(APHPFileName: string; lint: boolean=false): string;
  68. var
  69.   phpExe: string;
  70. begin
  71.   phpExe := GetPHPExe;
  72.   if phpExe = '' then Abort;
  73.   if lint then
  74.     result := GetDosOutput('"'+phpExe+'" -l "'+APHPFileName+'"', ExtractFileDir(ParamStr(0)))
  75.   else
  76.     result := GetDosOutput('"'+phpExe+'" -f "'+APHPFileName+'"', ExtractFileDir(ParamStr(0)));
  77. end;
  78.  
  79. function ParseCHM(const chmFile: TFileName): boolean;
  80. var
  81.   test, candidate, candidate2: string;
  82.   p, p2, q: integer;
  83.   i: integer;
  84.   good: Boolean;
  85.   ini: TMemIniFile;
  86.   domain: string;
  87.   sl: TStringList;
  88.   symbolCount: Integer;
  89.   sl2: TStrings;
  90.   outFile: string;
  91. begin
  92.   // TODO: problem:  mysqli::commit has /res/mysqli.commit.html -> keyword is NOT commit alone
  93.  
  94.   outFile := ChangeFileExt(chmFile, '.ini');
  95.   DeleteFile(outFile);
  96.   test := LoadFileToStr(chmFile);
  97.   if Pos('/php_manual_', test) = -1 then
  98.   begin
  99.     result := false;
  100.     exit;
  101.   end;
  102.   p := 0;
  103.   ini := TMemIniFile.Create(outFile);
  104.   try
  105.     ini.WriteString('_Info_', 'Source', chmFile);
  106.     ini.WriteString('_Info_', 'Generated', DateTimeToStr(Now));
  107.     ini.WriteString('_Info_', 'GeneratorVer', '1.0');
  108.     ini.WriteString('_Info_', 'Signature', '$ViaThinkSoft$');
  109.     {$REGION 'Excludes'}
  110.     // TODO: more excludes
  111.     ini.WriteBool('_HelpExclude_', 'about', true);
  112.     ini.WriteBool('_HelpExclude_', 'apache', true);
  113.     {$ENDREGION}
  114.     while true do
  115.     begin
  116.       if Assigned(Application) then Application.ProcessMessages;
  117.  
  118.       p := PosEx('/res/', Test, p+1);
  119.       if p = 0 then break;
  120.       p2 := PosEx('.html', Test, p);
  121.       if p = 0 then break;
  122.       candidate := copy(Test, p+5, p2-p-5);
  123.       if candidate = '' then continue;
  124.       if Length(candidate) > 50 then continue;
  125.       good := true;
  126.       for i := p+5 to p2-1 do
  127.       begin
  128.         if ord(test[i]) < 32 then
  129.         begin
  130.           good := false;
  131.           break;
  132.         end;
  133.         {$IFDEF UNICODE}
  134.         if not CharInSet(test[i], ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
  135.         {$ELSE}
  136.         if not (test[i] in ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
  137.         {$ENDIF}
  138.         begin
  139.           ini.WriteInteger('_Errors_', 'Contains unexpected character! ' + candidate, ini.ReadInteger('_Errors_', 'Contains unexpected character! ' + candidate, 0)+1);
  140.           good := false;
  141.           break;
  142.         end;
  143.       end;
  144.       if good then
  145.       begin
  146.         candidate2 := LowerCase(StringReplace(candidate, '-', '_', [rfReplaceAll]));
  147.         q := LastPos('.', candidate2);
  148.         domain := copy(candidate2, 1, q-1);
  149.         if domain = '' then continue;
  150.         candidate2 := copy(candidate2, q+1, Length(candidate2)-q);
  151.         ini.WriteInteger('_Category_', domain, ini.ReadInteger('_Category_', domain, 0)+1);
  152.         ini.WriteString(domain, candidate2, '/res/'+candidate+'.html');
  153.         if not ini.ReadBool('_HelpExclude_', domain, false)
  154.            and (candidate2 <> 'configuration')
  155.            and (candidate2 <> 'constants')
  156.            and (candidate2 <> 'installation')
  157.            and (candidate2 <> 'requirements')
  158.            and (candidate2 <> 'resources')
  159.            and (candidate2 <> 'setup') then
  160.         begin
  161.           if ini.ReadString('_HelpWords_', candidate2, '') <> '' then
  162.           begin
  163.             ini.WriteInteger('_Conflicts_', candidate2, ini.ReadInteger('_Conflicts_', candidate2, 0)+1);
  164.           end;
  165.  
  166.           ini.WriteString('_HelpWords_', candidate2, '/res/'+candidate+'.html');
  167.         end;
  168.       end;
  169.     end;
  170.  
  171.     sl := TStringList.Create;
  172.     sl2 := TStringList.Create;
  173.     try
  174.       ini.ReadSections(sl);
  175.       ini.WriteInteger('_Info_', 'TotalDomains', sl.Count);
  176.       symbolCount := 0;
  177.       for domain in sl do
  178.       begin
  179.         ini.ReadSection(domain, sl2);
  180.         Inc(symbolCount, sl2.Count)
  181.       end;
  182.       ini.WriteInteger('_Info_', 'TotalSymbols', symbolCount);
  183.     finally
  184.       sl.Free;
  185.       sl2.Free;
  186.     end;
  187.  
  188.     ini.UpdateFile;
  189.     result := true;
  190.   finally
  191.     ini.Free;
  192.   end;
  193. end;
  194.  
  195. function IsValidPHPExe(const exeFile: TFileName): boolean;
  196. var
  197.   cont: string;
  198. begin
  199.   cont := LoadFileToStr(exeFile);
  200.   result := (Pos('php://stdout', cont) >= 0) or
  201.             (Pos('PHP_SELF', cont) >= 0);
  202. end;
  203.  
  204. initialization
  205. finalization
  206.   if Assigned(__FastPHPConfig) then
  207.   begin
  208.     __FastPHPConfig.UpdateFile;
  209.     FreeAndNil(__FastPHPConfig);
  210.   end;
  211. end.
  212.