Subversion Repositories fastphp

Rev

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