Subversion Repositories fastphp

Rev

Rev 42 | Rev 49 | 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
45 daniel-mar 6
  Windows, SysUtils, StrUtils, Dialogs, IniFiles, Classes, Forms, ShellAPI;
8 daniel-mar 7
 
8
const
9
  FASTPHP_GOTO_URI_PREFIX = 'fastphp://editor/gotoline/';
10
 
11
function FastPHPConfig: TMemIniFile;
12
function GetPHPExe: string;
45 daniel-mar 13
function RunPHPScript(APHPFileName: string; lint: boolean=false; inConsole: boolean=False): string;
13 daniel-mar 14
function ParseCHM(const chmFile: TFileName): boolean;
15
function IsValidPHPExe(const exeFile: TFileName): boolean;
8 daniel-mar 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
16 daniel-mar 29
    __FastPHPConfig := TMemIniFile.Create(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + 'FastPHP.ini');
8 daniel-mar 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
 
45 daniel-mar 67
function RunPHPScript(APHPFileName: string; lint: boolean=false; inConsole: boolean=False): string;
8 daniel-mar 68
var
45 daniel-mar 69
  phpExe, args, batFile, workdir: string;
70
  slBat: TStringList;
8 daniel-mar 71
begin
72
  phpExe := GetPHPExe;
73
  if phpExe = '' then Abort;
45 daniel-mar 74
 
33 daniel-mar 75
  if lint then
45 daniel-mar 76
    args := '-l "'+APHPFileName+'"'
33 daniel-mar 77
  else
45 daniel-mar 78
    args := '-f "'+APHPFileName+'"';
79
 
80
  //workdir := ExtractFileDir(ParamStr(0));
81
  workdir := ExtractFileDir(APHPFileName);
82
 
83
  if inConsole then
84
  begin
85
    (*
86
    ShellExecute(0, 'open', PChar(phpExe), PChar(args), PChar(workdir), SW_NORMAL);
87
    *)
88
    batFile := IncludeTrailingPathDelimiter(GetTempDir) + 'RunFastPHP.bat';
89
    slBat := TStringList.Create;
90
    try
91
      slBat.Add('@echo off');
92
      slBat.Add('cd /d "'+workdir+'"');
93
      slBat.Add('"'+phpExe+'" ' + args);
94
      slBat.Add('pause.');
95
      slBat.SaveToFile(batFile);
96
      ShellExecute(0, 'open', PChar(batFile), '', '', SW_NORMAL);
97
    finally
98
      slBat.Free;
99
    end;
100
 
101
    result := '';
102
  end
103
  else
104
  begin
105
    result := GetDosOutput('"'+phpExe+'" ' + args, workdir);
106
  end;
8 daniel-mar 107
end;
108
 
13 daniel-mar 109
function ParseCHM(const chmFile: TFileName): boolean;
8 daniel-mar 110
var
111
  test, candidate, candidate2: string;
112
  p, p2, q: integer;
113
  i: integer;
114
  good: Boolean;
115
  ini: TMemIniFile;
116
  domain: string;
117
  sl: TStringList;
118
  symbolCount: Integer;
119
  sl2: TStrings;
120
  outFile: string;
121
begin
122
  // TODO: problem:  mysqli::commit has /res/mysqli.commit.html -> keyword is NOT commit alone
123
 
124
  outFile := ChangeFileExt(chmFile, '.ini');
125
  DeleteFile(outFile);
126
  test := LoadFileToStr(chmFile);
127
  if Pos('/php_manual_', test) = -1 then
128
  begin
129
    result := false;
130
    exit;
131
  end;
132
  p := 0;
133
  ini := TMemIniFile.Create(outFile);
134
  try
135
    ini.WriteString('_Info_', 'Source', chmFile);
136
    ini.WriteString('_Info_', 'Generated', DateTimeToStr(Now));
137
    ini.WriteString('_Info_', 'GeneratorVer', '1.0');
138
    ini.WriteString('_Info_', 'Signature', '$ViaThinkSoft$');
139
    {$REGION 'Excludes'}
140
    // TODO: more excludes
141
    ini.WriteBool('_HelpExclude_', 'about', true);
142
    ini.WriteBool('_HelpExclude_', 'apache', true);
143
    {$ENDREGION}
144
    while true do
145
    begin
146
      if Assigned(Application) then Application.ProcessMessages;
147
 
148
      p := PosEx('/res/', Test, p+1);
149
      if p = 0 then break;
150
      p2 := PosEx('.html', Test, p);
151
      if p = 0 then break;
152
      candidate := copy(Test, p+5, p2-p-5);
153
      if candidate = '' then continue;
154
      if Length(candidate) > 50 then continue;
155
      good := true;
156
      for i := p+5 to p2-1 do
157
      begin
158
        if ord(test[i]) < 32 then
159
        begin
160
          good := false;
161
          break;
162
        end;
25 daniel-mar 163
        {$IFDEF UNICODE}
8 daniel-mar 164
        if not CharInSet(test[i], ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
25 daniel-mar 165
        {$ELSE}
166
        if not (test[i] in ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
167
        {$ENDIF}
8 daniel-mar 168
        begin
169
          ini.WriteInteger('_Errors_', 'Contains unexpected character! ' + candidate, ini.ReadInteger('_Errors_', 'Contains unexpected character! ' + candidate, 0)+1);
170
          good := false;
171
          break;
172
        end;
173
      end;
174
      if good then
175
      begin
176
        candidate2 := LowerCase(StringReplace(candidate, '-', '_', [rfReplaceAll]));
177
        q := LastPos('.', candidate2);
178
        domain := copy(candidate2, 1, q-1);
179
        if domain = '' then continue;
180
        candidate2 := copy(candidate2, q+1, Length(candidate2)-q);
181
        ini.WriteInteger('_Category_', domain, ini.ReadInteger('_Category_', domain, 0)+1);
182
        ini.WriteString(domain, candidate2, '/res/'+candidate+'.html');
183
        if not ini.ReadBool('_HelpExclude_', domain, false)
184
           and (candidate2 <> 'configuration')
185
           and (candidate2 <> 'constants')
186
           and (candidate2 <> 'installation')
187
           and (candidate2 <> 'requirements')
188
           and (candidate2 <> 'resources')
189
           and (candidate2 <> 'setup') then
190
        begin
191
          if ini.ReadString('_HelpWords_', candidate2, '') <> '' then
192
          begin
193
            ini.WriteInteger('_Conflicts_', candidate2, ini.ReadInteger('_Conflicts_', candidate2, 0)+1);
194
          end;
195
 
196
          ini.WriteString('_HelpWords_', candidate2, '/res/'+candidate+'.html');
197
        end;
198
      end;
199
    end;
200
 
201
    sl := TStringList.Create;
202
    sl2 := TStringList.Create;
203
    try
204
      ini.ReadSections(sl);
205
      ini.WriteInteger('_Info_', 'TotalDomains', sl.Count);
206
      symbolCount := 0;
207
      for domain in sl do
208
      begin
209
        ini.ReadSection(domain, sl2);
210
        Inc(symbolCount, sl2.Count)
211
      end;
212
      ini.WriteInteger('_Info_', 'TotalSymbols', symbolCount);
213
    finally
214
      sl.Free;
215
      sl2.Free;
216
    end;
217
 
218
    ini.UpdateFile;
219
    result := true;
220
  finally
221
    ini.Free;
222
  end;
223
end;
224
 
13 daniel-mar 225
function IsValidPHPExe(const exeFile: TFileName): boolean;
9 daniel-mar 226
var
227
  cont: string;
228
begin
229
  cont := LoadFileToStr(exeFile);
230
  result := (Pos('php://stdout', cont) >= 0) or
231
            (Pos('PHP_SELF', cont) >= 0);
232
end;
233
 
8 daniel-mar 234
initialization
235
finalization
236
  if Assigned(__FastPHPConfig) then
237
  begin
238
    __FastPHPConfig.UpdateFile;
239
    FreeAndNil(__FastPHPConfig);
240
  end;
241
end.