Subversion Repositories fastphp

Rev

Rev 61 | 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
83 daniel-mar 6
  Windows, SysUtils, StrUtils, Dialogs, IniFiles, Classes, Forms, ShellAPI, Functions,
7
  System.UITypes;
8 daniel-mar 8
 
9
const
10
  FASTPHP_GOTO_URI_PREFIX = 'fastphp://editor/gotoline/';
11
 
12
function GetPHPExe: string;
61 daniel-mar 13
function RunPHPScript(APHPFileName: string; lint: boolean=false; inConsole: boolean=False; ContentCallBack: TContentCallBack=nil): 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
61 daniel-mar 20
  FastPHPConfig;
8 daniel-mar 21
 
22
function GetPHPExe: string;
23
var
24
  od: TOpenDialog;
25
begin
49 daniel-mar 26
  result := TFastPHPConfig.PhpInterpreter;
8 daniel-mar 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];
49 daniel-mar 35
      od.Title := 'Please choose your PHP interpreter (php.exe)';
8 daniel-mar 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
49 daniel-mar 46
      MessageDlg('This is not a valid PHP executable.', mtError, [mbOk], 0);
8 daniel-mar 47
      exit;
48
    end;
49
 
49 daniel-mar 50
    TFastPHPConfig.PhpInterpreter := result;
8 daniel-mar 51
  end;
52
end;
53
 
61 daniel-mar 54
function RunPHPScript(APHPFileName: string; lint: boolean=false; inConsole: boolean=False; ContentCallBack: TContentCallBack=nil): string;
8 daniel-mar 55
var
45 daniel-mar 56
  phpExe, args, batFile, workdir: string;
57
  slBat: TStringList;
8 daniel-mar 58
begin
59
  phpExe := GetPHPExe;
60
  if phpExe = '' then Abort;
45 daniel-mar 61
 
33 daniel-mar 62
  if lint then
45 daniel-mar 63
    args := '-l "'+APHPFileName+'"'
33 daniel-mar 64
  else
45 daniel-mar 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
61 daniel-mar 92
    result := GetDosOutput('"'+phpExe+'" ' + args, workdir, ContentCallBack);
45 daniel-mar 93
  end;
8 daniel-mar 94
end;
95
 
13 daniel-mar 96
function ParseCHM(const chmFile: TFileName): boolean;
8 daniel-mar 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);
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;
25 daniel-mar 150
        {$IFDEF UNICODE}
8 daniel-mar 151
        if not CharInSet(test[i], ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
25 daniel-mar 152
        {$ELSE}
153
        if not (test[i] in ['a'..'z', 'A'..'Z', '.', '-', '_', '0'..'9']) then
154
        {$ENDIF}
8 daniel-mar 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
 
13 daniel-mar 212
function IsValidPHPExe(const exeFile: TFileName): boolean;
9 daniel-mar 213
var
214
  cont: string;
215
begin
216
  cont := LoadFileToStr(exeFile);
217
  result := (Pos('php://stdout', cont) >= 0) or
218
            (Pos('PHP_SELF', cont) >= 0);
219
end;
220
 
8 daniel-mar 221
end.