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