Subversion Repositories fastphp

Rev

Rev 49 | Rev 83 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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