Subversion Repositories fastphp

Rev

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