Subversion Repositories fastphp

Rev

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

  1. unit Functions;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, StrUtils, IniFiles, Classes, Forms, Variants, MsHTML,
  7.   SHDocVw_TLB, StdCtrls, SynEdit,
  8.  
  9.  
  10.  
  11.  
  12.  
  13.   dialogs;
  14.  
  15. function GetDosOutput(CommandLine: string; Work: string = ''): string;
  16. function StrIPos(const SubStr, S: string): Integer;
  17. procedure WaitForBrowser(WB: TWebbrowser);
  18. function LoadFileToStr(const FileName: TFileName): AnsiString;
  19. function LastPos(const SubStr, S: string): integer;
  20. function ParseCHM(chmFile: string): boolean;
  21. procedure BrowseURL(WebBrowser1: TWebBrowser; url: string);
  22. procedure BrowseContent(WebBrowser1: TWebBrowser; html: string);
  23. function IsTextHTML(s: string): boolean;
  24. function GetWordUnderCaret(AMemo: TSynEdit): string;
  25. function IsValidPHPExe(const exeFile: string): boolean;
  26.  
  27. implementation
  28.  
  29. function GetDosOutput(CommandLine: string; Work: string = ''): string;
  30. var
  31.   SA: TSecurityAttributes;
  32.   SI: TStartupInfo;
  33.   PI: TProcessInformation;
  34.   StdOutPipeRead, StdOutPipeWrite: THandle;
  35.   WasOK: Boolean;
  36.   Buffer: array[0..255] of AnsiChar;
  37.   BytesRead: Cardinal;
  38.   WorkDir: string;
  39.   Handle: Boolean;
  40. begin
  41.   if Work = '' then Work := ExtractFilePath(ParamStr(0));
  42.  
  43.   Result := '';
  44.   with SA do begin
  45.     nLength := SizeOf(SA);
  46.     bInheritHandle := True;
  47.     lpSecurityDescriptor := nil;
  48.   end;
  49.   CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
  50.   try
  51.     with SI do
  52.     begin
  53.       FillChar(SI, SizeOf(SI), 0);
  54.       cb := SizeOf(SI);
  55.       dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  56.       wShowWindow := SW_HIDE;
  57.       hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
  58.       hStdOutput := StdOutPipeWrite;
  59.       hStdError := StdOutPipeWrite;
  60.     end;
  61.     WorkDir := Work;
  62.     Handle := CreateProcess(nil, PChar('cmd.exe /C "' + CommandLine + '"'),
  63.                             nil, nil, True, 0, nil,
  64.                             PChar(WorkDir), SI, PI);
  65.     CloseHandle(StdOutPipeWrite);
  66.     if Handle then
  67.       try
  68.         repeat
  69.           WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
  70.           if BytesRead > 0 then
  71.           begin
  72.             Buffer[BytesRead] := #0;
  73.             Result := Result + Buffer;
  74.           end;
  75.         until not WasOK or (BytesRead = 0);
  76.         WaitForSingleObject(PI.hProcess, INFINITE);
  77.       finally
  78.         CloseHandle(PI.hThread);
  79.         CloseHandle(PI.hProcess);
  80.       end;
  81.   finally
  82.     CloseHandle(StdOutPipeRead);
  83.   end;
  84. end;
  85.  
  86. function StrIPos(const SubStr, S: string): Integer;
  87. begin
  88.   Result := Pos(UpperCase(SubStr), UpperCase(S));
  89. end;
  90.  
  91. procedure WaitForBrowser(WB: TWebbrowser);
  92. begin
  93.   while (WB.Busy)
  94.     and not (Application.Terminated) do
  95.   begin
  96.     Application.ProcessMessages;
  97.     Sleep(100);
  98.   end;
  99. end;
  100.  
  101. function LoadFileToStr(const FileName: TFileName): AnsiString;
  102. var
  103.   FileStream : TFileStream;
  104.  
  105. begin
  106.   Result:= '';
  107.   FileStream:= TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  108.   try
  109.     if FileStream.Size>0 then begin
  110.       SetLength(Result, FileStream.Size);
  111.       FileStream.Read(Result[1], FileStream.Size);
  112.     end;
  113.   finally
  114.     FileStream.Free;
  115.   end;
  116. end;
  117.  
  118. function LastPos(const SubStr, S: string): integer;
  119. var
  120.   I, J, K: integer;
  121. begin
  122.   Result := 0;
  123.   I := Length(S);
  124.   K := Length(SubStr);
  125.   if (K = 0) or (K > I) then
  126.     Exit;
  127.   while (Result = 0) and (I >= K) do
  128.   begin
  129.     J := K;
  130.     if S[I] = SubStr[J] then
  131.     begin
  132.       while (J > 1) and (S[I + J - K - 1] = SubStr[J - 1]) do
  133.         Dec(J);
  134.       if J = 1 then
  135.         Result := I - K + 1;
  136.     end;
  137.     Dec(I);
  138.   end;
  139. end;
  140.  
  141. function ParseCHM(chmFile: string): boolean;
  142. var
  143.   test, candidate, candidate2: string;
  144.   p, p2, q: integer;
  145.   i: integer;
  146.   good: Boolean;
  147.   ini: TMemIniFile;
  148.   domain: string;
  149.   sl: TStringList;
  150.   symbolCount: Integer;
  151.   sl2: TStrings;
  152.   outFile: string;
  153. begin
  154.   // TODO: problem:  mysqli::commit has /res/mysqli.commit.html -> keyword is NOT commit alone
  155.  
  156.   outFile := ChangeFileExt(chmFile, '.ini');
  157.   DeleteFile(outFile);
  158.   test := LoadFileToStr(chmFile);
  159.   if Pos('/php_manual_', test) = -1 then
  160.   begin
  161.     result := false;
  162.     exit;
  163.   end;
  164.   p := 0;
  165.   ini := TMemIniFile.Create(outFile);
  166.   try
  167.     ini.WriteString('_Info_', 'Source', chmFile);
  168.     ini.WriteString('_Info_', 'Generated', DateTimeToStr(Now));
  169.     ini.WriteString('_Info_', 'GeneratorVer', '1.0');
  170.     ini.WriteString('_Info_', 'Signature', '$ViaThinkSoft$');
  171.     {$REGION 'Excludes'}
  172.     // TODO: more excludes
  173.     ini.WriteBool('_HelpExclude_', 'about', true);
  174.     ini.WriteBool('_HelpExclude_', 'apache', true);
  175.     {$ENDREGION}
  176.     while true do
  177.     begin
  178.       Application.ProcessMessages;
  179.  
  180.       p := PosEx('/res/', Test, p+1);
  181.       if p = 0 then break;
  182.       p2 := PosEx('.html', Test, p);
  183.       if p = 0 then break;
  184.       candidate := copy(Test, p+5, p2-p-5);
  185.       if candidate = '' then continue;
  186.       if Length(candidate) > 50 then continue;
  187.       good := true;
  188.       for i := p+5 to p2-1 do
  189.       begin
  190.         if ord(test[i]) < 32 then
  191.         begin
  192.           good := false;
  193.           break;
  194.         end;
  195.         if not (test[i] in ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
  196.         begin
  197.           ini.WriteInteger('_Errors_', 'Contains unexpected character! ' + candidate, ini.ReadInteger('_Errors_', 'Contains unexpected character! ' + candidate, 0)+1);
  198.           good := false;
  199.           break;
  200.         end;
  201.       end;
  202.       if good then
  203.       begin
  204.         candidate2 := LowerCase(StringReplace(candidate, '-', '_', [rfReplaceAll]));
  205.         q := LastPos('.', candidate2);
  206.         domain := copy(candidate2, 1, q-1);
  207.         if domain = '' then continue;
  208.         candidate2 := copy(candidate2, q+1, Length(candidate2)-q);
  209.         ini.WriteInteger('_Category_', domain, ini.ReadInteger('_Category_', domain, 0)+1);
  210.         ini.WriteString(domain, candidate2, '/res/'+candidate+'.html');
  211.         if not ini.ReadBool('_HelpExclude_', domain, false)
  212.            and (candidate2 <> 'configuration')
  213.            and (candidate2 <> 'constants')
  214.            and (candidate2 <> 'installation')
  215.            and (candidate2 <> 'requirements')
  216.            and (candidate2 <> 'resources')
  217.            and (candidate2 <> 'setup') then
  218.         begin
  219.           if ini.ReadString('_HelpWords_', candidate2, '') <> '' then
  220.           begin
  221.             ini.WriteInteger('_Conflicts_', candidate2, ini.ReadInteger('_Conflicts_', candidate2, 0)+1);
  222.           end;
  223.  
  224.           ini.WriteString('_HelpWords_', candidate2, '/res/'+candidate+'.html');
  225.         end;
  226.       end;
  227.     end;
  228.  
  229.     sl := TStringList.Create;
  230.     sl2 := TStringList.Create;
  231.     try
  232.       ini.ReadSections(sl);
  233.       ini.WriteInteger('_Info_', 'TotalDomains', sl.Count);
  234.       symbolCount := 0;
  235.       for domain in sl do
  236.       begin
  237.         ini.ReadSection(domain, sl2);
  238.         Inc(symbolCount, sl2.Count)
  239.       end;
  240.       ini.WriteInteger('_Info_', 'TotalSymbols', symbolCount);
  241.     finally
  242.       sl.Free;
  243.       sl2.Free;
  244.     end;
  245.  
  246.     ini.UpdateFile;
  247.     result := true;
  248.   finally
  249.     ini.Free;
  250.   end;
  251. end;
  252.  
  253. procedure BrowseURL(WebBrowser1: TWebBrowser; url: string);
  254. var
  255.   BrowserFlags : olevariant;
  256.   MyTargetFrameName : olevariant;
  257.   MyPostaData : olevariant;
  258.   MyHeaders : olevariant;
  259. begin
  260. { Flags:
  261. Constant            Value Meaning
  262. NavOpenInNewWindow  $01  Open the resource or file in a new window.
  263. NavNoHistory        $02  Do not add the resource or file to the history list. The new page replaces the current page in the list.
  264. NavNoReadFromCache  $04  Do not read from the disk cache for this navigation.
  265. NavNoWriteToCache   $08  Do not write the results of this navigation to the disk cache.
  266. NavAllowAutosearch  $10  If the navigation fails, the Web browser attempts to navigate common root domains (.com, .org, and so on). If this still fails, the URL is passed to a search engine.
  267. }
  268.   BrowserFlags := $02;
  269.   MyTargetFrameName := null;
  270.   MyPostaData := null;
  271.   MyHeaders := null;
  272.   WebBrowser1.Silent := true; // no JavaScript errors
  273.   Webbrowser1.Navigate(url, BrowserFlags,MyTargetFrameName,MyPostaData,MyHeaders);
  274.   WaitForBrowser(WebBrowser1);
  275. end;
  276.  
  277. procedure BrowseContent(WebBrowser1: TWebBrowser; html: string);
  278. var
  279.   BrowserFlags : olevariant;
  280.   MyTargetFrameName : olevariant;
  281.   MyPostaData : olevariant;
  282.   MyHeaders : olevariant;
  283.   Doc: Variant;
  284. begin
  285. { Flags:
  286. Constant            Value Meaning
  287. NavOpenInNewWindow  $01  Open the resource or file in a new window.
  288. NavNoHistory        $02  Do not add the resource or file to the history list. The new page replaces the current page in the list.
  289. NavNoReadFromCache  $04  Do not read from the disk cache for this navigation.
  290. NavNoWriteToCache   $08  Do not write the results of this navigation to the disk cache.
  291. NavAllowAutosearch  $10  If the navigation fails, the Web browser attempts to navigate common root domains (.com, .org, and so on). If this still fails, the URL is passed to a search engine.
  292. }
  293.   if WebBrowser1.Document = nil then
  294.   begin
  295.     BrowserFlags := $02 + $04 + $08 + $10;
  296.     MyTargetFrameName := null;
  297.     MyPostaData := null;
  298.     MyHeaders := null;
  299.     Webbrowser1.Navigate('about:blank', BrowserFlags,MyTargetFrameName,MyPostaData,MyHeaders);
  300.     WaitForBrowser(WebBrowser1);
  301.   end;
  302.  
  303.   Doc := WebBrowser1.Document;
  304.   Doc.Clear;
  305.   Doc.Write(html);
  306.   Doc.Close;
  307.   WaitForBrowser(WebBrowser1);
  308. end;
  309.  
  310. function IsTextHTML(s: string): boolean;
  311.  
  312.   function _Tag(const tag: string): integer;
  313.   begin
  314.     result := 0;
  315.     if (StrIPos('<'+tag+'>', s) > 0) then Inc(result);
  316.     if (StrIPos('</'+tag+'>', s) > 0) then Inc(result);
  317.     if (StrIPos('<'+tag+' />', s) > 0) then Inc(result);
  318.     if (StrIPos('<'+tag+' ', s) > 0) then Inc(result);
  319.   end;
  320.  
  321. var
  322.   score: integer;
  323. begin
  324.   score := _Tag('html') + _Tag('body') + _Tag('p') + _Tag('a') + _Tag('b') +
  325.            _Tag('i') + _Tag('u') + _Tag('li') + _Tag('ol') + _Tag('ul') +
  326.            _Tag('img') + _Tag('div') + _Tag('hr') + _Tag('code') +
  327.            _Tag('pre') + _Tag('blockquote') + _Tag('span');
  328.   result := score >= 2;
  329. end;
  330.  
  331. // Template: http://stackoverflow.com/questions/6339446/delphi-get-the-whole-word-where-the-caret-is-in-a-memo
  332. function GetWordUnderCaret(AMemo: TSynEdit): string;
  333.  
  334.   function ValidChar(c: char): boolean;
  335.   begin
  336.     result := c in ['a'..'z', 'A'..'Z', '0'..'9', '_'];
  337.   end;
  338.  
  339. var
  340.    Line    : Integer;
  341.    Column  : Integer;
  342.    LineText: string;
  343.    InitPos : Integer;
  344.    EndPos  : Integer;
  345. begin
  346.    //Get the caret position
  347.    (*
  348.    if AMemo is TMemo then
  349.    begin
  350.      Line   := AMemo.Perform(EM_LINEFROMCHAR,AMemo.SelStart, 0);
  351.      Column := AMemo.SelStart - AMemo.Perform(EM_LINEINDEX, Line, 0);
  352.    end;
  353.    if AMemo is TSynEdit then
  354.    begin
  355.    *)
  356.      Line := AMemo.CaretY-1;
  357.      Column := AMemo.CaretX-1;
  358.    (*
  359.    end;
  360.    *)
  361.  
  362.    //Validate the line number
  363.    if AMemo.Lines.Count-1 < Line then Exit;
  364.  
  365.    //Get the text of the line
  366.    LineText := AMemo.Lines[Line];
  367.  
  368.    if LineText = '' then exit('');
  369.  
  370.    // Column zeigt auf das Zeichen LINKS vom Cursor!
  371.  
  372.    InitPos := Column;
  373.    if not ValidChar(LineText[InitPos]) then Inc(InitPos);
  374.    while (InitPos-1 >= 1) and ValidChar(LineText[InitPos-1]) do Dec(InitPos);
  375.  
  376.    EndPos := Column;
  377.    while (EndPos+1 <= Length(LineText)) and ValidChar(LineText[EndPos+1]) do Inc(EndPos);
  378.  
  379.    //Get the text
  380.    Result := Copy(LineText, InitPos, EndPos - InitPos + 1);
  381. end;
  382.  
  383. function IsValidPHPExe(const exeFile: string): boolean;
  384. var
  385.   cont: string;
  386. begin
  387.   cont := LoadFileToStr(exeFile);
  388.   result := (Pos('php://stdout', cont) >= 0) or
  389.             (Pos('PHP_SELF', cont) >= 0);
  390. end;
  391.  
  392. end.
  393.