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. |