Subversion Repositories fastphp

Rev

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