478 lines
18 KiB
PHP
478 lines
18 KiB
PHP
constructor THeoGorDownPDFThread.Create (AOnTerminate: TNotifyEvent; AService: TService);
|
|
begin
|
|
inherited Create (false); // Create thread in NOT suspended mode
|
|
FMainService:= AService;
|
|
FLock:= TCriticalSection.Create;
|
|
FRunning:= false;
|
|
FTermEvent:= TEvent.Create (nil, False, False, '');
|
|
|
|
|
|
// OnTerminate:= AOnTerminate;
|
|
// FreeOnTerminate:= true;
|
|
FreeOnTerminate:= false; // Ensure manual freeing of thread resources
|
|
end;
|
|
|
|
|
|
|
|
|
|
destructor THeoGorDownPDFThread.Destroy;
|
|
begin
|
|
{$IFDEF DEBUG}
|
|
Write('Ukoncuji thread GOR Download PDF...');
|
|
{$ENDIF}
|
|
if (FTimer<>0) then
|
|
CloseHandle (FTimer);
|
|
FTermEvent.Free;
|
|
FRunning:= false;
|
|
FMainService:= nil;
|
|
Terminate;
|
|
FLock.Free;
|
|
inherited;
|
|
{$IFDEF DEBUG}
|
|
WriteLn('OK');
|
|
{$ENDIF}
|
|
end;
|
|
|
|
|
|
|
|
procedure THeoGorDownPDFThread.TerminatedSet;
|
|
begin
|
|
FTermEvent.SetEvent;
|
|
end;
|
|
|
|
|
|
|
|
procedure THeoGorDownPDFThread.ThreadTerminate;
|
|
begin
|
|
Terminate;
|
|
WaitFor;
|
|
end;
|
|
|
|
|
|
|
|
procedure THeoGorDownPDFThread.Execute;
|
|
const _Second = 10_000_000;
|
|
var lSQL, errMsg, url, outData, fName, loopCasTyp: string;
|
|
lLoop, idDigiFile, cnt, idx: Integer;
|
|
lLoopMax, koefProCas: integer;
|
|
logRunCnt: integer;
|
|
Msg: TMsg;
|
|
firstRun, inProg, inDL: boolean;
|
|
lQry: TFDQuery;
|
|
sqlConnX, sqlConnX2: TFDConnection;
|
|
sqlTrans: IFDPhysTransaction;
|
|
f, lOpenSSLLib: string;
|
|
|
|
lBusy: LongInt;
|
|
liDueTime: LARGE_INTEGER;
|
|
|
|
mamSSLLibs: boolean;
|
|
sslLibPath: string;
|
|
http1: System.Net.HTTPClient.THTTPClient;
|
|
iResp: System.Net.HTTPClient.IHTTPResponse;
|
|
aResp: TMemoryStream;
|
|
http2: TIdHttp;
|
|
sslHndlr: TIdSSLIOHandlerSocketOpenSSL;
|
|
respHttp2: TStream;
|
|
i: integer;
|
|
sTemp, outData2: string;
|
|
|
|
cfgFile: string;
|
|
specCfgXML: XML.XmlIntf.IXMLDocument;
|
|
n1: XML.XmlIntf.IXMLNode;
|
|
attribs: IXMLNodeList;
|
|
attrIdx: integer;
|
|
|
|
function StringToHex (const inStr: string): string;
|
|
var i: integer;
|
|
begin
|
|
result:= '';
|
|
for i:=1 to Length(inStr) do
|
|
result:= result + IntToHex(Ord(inStr[i]), 2); // 2 means two hex digits per character
|
|
end;
|
|
|
|
function MemStreamToHex (aStream: TMemoryStream): string;
|
|
var i: integer;
|
|
b: byte;
|
|
begin
|
|
result:= '';
|
|
for i:=0 to aStream.Size-1 do
|
|
begin
|
|
b:= PByte(TMemoryStream(aStream).Memory)[i];
|
|
result:= result + IntToHex(b,2);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
lLoop:= 0;
|
|
idDigiFile:= 0;
|
|
logRunCnt:= 1;
|
|
|
|
{
|
|
koefProCas:= 0; // default vteriny
|
|
loopCasTyp:= '???';
|
|
case DZTaksZapisTypCas of
|
|
0: koefProCas:= 1;
|
|
1: koefProCas:= 60;
|
|
2: koefProCas:= 3600;
|
|
end;
|
|
lLoopMax:= koefProCas * intProcessDZTasksSec;
|
|
case DZTaksZapisTypCas of
|
|
0: loopCasTyp:= 'sek';
|
|
1: loopCasTyp:= 'min';
|
|
2: loopCasTyp:= 'hod';
|
|
end;
|
|
}
|
|
|
|
lLoopMax:= 10; // v minutach !!!!
|
|
try
|
|
try
|
|
CoInitialize(nil);
|
|
cfgFile:= ExtractFilePath(ParamStr(0)) + 'gornicky.xml';
|
|
if (FileExists(cfgFile)) then
|
|
begin
|
|
specCfgXML:= Xml.XMLDoc.TXMLDocument.Create(nil);
|
|
specCfgXML.LoadFromFile (cfgFile);
|
|
specCfgXML.Active:= true;
|
|
if not(specCfgXML.IsEmptyDoc) then
|
|
begin
|
|
if (specCfgXML.DocumentElement<>nil) then
|
|
begin
|
|
n1:= specCfgXML.DocumentElement;
|
|
if (n1.NodeName='config') then
|
|
begin
|
|
attribs:= n1.AttributeNodes;
|
|
|
|
attrIdx:= attribs.IndexOf('downPDFintMins');
|
|
if (attrIdx>-1) then
|
|
if (attribs.Get(attrIdx).NodeValue<>null) then
|
|
lLoopMax:= attribs.Get(attrIdx).NodeValue;
|
|
end; // n1 = config
|
|
end; // specCfgXML.DocumentElement<>nil
|
|
end; // not specCfgXML.IsEmptyDoc
|
|
end; // FileExists(cfgFile)
|
|
except
|
|
end;
|
|
finally
|
|
begin
|
|
if (specCfgXML<>nil) then
|
|
specCfgXML:= nil;
|
|
CoUninitialize;
|
|
end;
|
|
end;
|
|
|
|
datMod.LogInfo (Quick.Logger.etInfo, 'Download PDF interval: ' + lLoopMax.ToString + ' min.');
|
|
lLoopMax:= lLoopMax * 60; // minuty na vteriny
|
|
|
|
|
|
firstRun:= true;
|
|
inProg:= false;
|
|
|
|
sslLibPath:= '';
|
|
f:= ExtractFilePath (ParamStr(0));
|
|
mamSSLLibs:= false;
|
|
for lOpenSSLLib in OPENSSL_LIBS do
|
|
begin
|
|
if (FileExists(TPath.Combine(f, lOpenSSLLib))) then
|
|
begin
|
|
mamSSLLibs:= true;
|
|
sslLibPath:= ExcludeTrailingPathDelimiter (f);
|
|
end;
|
|
end;
|
|
|
|
|
|
FRunning:= false;
|
|
if not(datMod.SQLTableExists(tblAPIDigiSoubory)) then
|
|
Exit;
|
|
|
|
FRunning:= true;
|
|
|
|
|
|
if (1=1) then // pro rychle vypnuti
|
|
begin
|
|
FTimer:= CreateWaitableTimer (nil, true, 'GorDownloadPDFWaitableTimer');
|
|
liDueTime.QuadPart:= -1*_Second;
|
|
|
|
|
|
try
|
|
while not(Terminated) or not(FRunning) do
|
|
begin
|
|
if (HDCDZApiService<>nil) then
|
|
if (HDCDZApiService.Terminated) then
|
|
begin
|
|
Terminate;
|
|
FRunning:= false;
|
|
end;
|
|
|
|
PeekMessage (&Msg, 0, 0, 0, PM_NOREMOVE); { Create message queue }
|
|
|
|
if (lLoop=lLoopMax) or (firstRun) then // pri startu a pak kazdou minutu
|
|
begin
|
|
idDigiFile:= 0;
|
|
firstRun:= false;
|
|
|
|
if (logRunCnt<4) then
|
|
datMod.LogInfo (Quick.Logger.etInfo, 'Spoustim download ' + logRunCnt.toString + '...');
|
|
if (logRunCnt=4) then
|
|
datMod.LogInfo (Quick.Logger.etInfo, 'Spoustim download - bezi ale dal neloguju');
|
|
|
|
try
|
|
if not(inProg) then // nebezi uz ?
|
|
begin
|
|
|
|
if (1=1) then // pro rychle vypnuti
|
|
begin
|
|
|
|
sqlConnX:= TFDConnection.Create (nil);
|
|
sqlConnX.Params.SetStrings (datMod.sqlConnParams);
|
|
// sqlConnX.TxOptions.AutoCommit:= false;
|
|
sqlConnX.Open;
|
|
|
|
if (sqlConnX.Connected) then
|
|
begin
|
|
// sqlConnX.ExecSQL('DECLARE @i INT; SET @i=ISNULL( (SELECT MAX(ID) FROM dbo.TabDokumenty), 1); DBCC CHECKIDENT (TabDokumenty, RESEED, @i)');
|
|
|
|
lSQL:= '/* hdcDZApiSvc */ SELECT ID FROM ' + tblAPIDigiSoubory + ' WHERE Blokovano=0 AND Zpracovano=0 AND Zpracovat=1'
|
|
+ ' AND IDDokument IS NULL ORDER BY ID';
|
|
|
|
lQry:= TFDQuery.Create(nil);
|
|
try
|
|
lQry.Connection:= sqlConnX;
|
|
lQry.Open(lSQL);
|
|
if (lQry.RecordCount>0) then
|
|
begin
|
|
lQry.First;
|
|
if (sqlConnX.TxOptions.AutoCommit=false) then
|
|
sqlConnX.StartTransaction;
|
|
inProg:= true;
|
|
|
|
while not(lQry.EOF) do
|
|
begin
|
|
|
|
PeekMessage (&Msg, 0, 0, 0, PM_NOREMOVE); { Create message queue }
|
|
helUtils.ProcessPendingVCLMessages;
|
|
|
|
idDigiFile:= lQry.FieldByName('ID').asInteger;
|
|
if (idDigiFile>0) then
|
|
begin
|
|
try
|
|
// musim to zablokovat uz tady aby se to nezpracovavalo znovu
|
|
sqlConnX.ExecSQL('UPDATE ' + tblAPIDigiSoubory + ' SET Blokovano=1 WHERE ID=' + idDigiFile.ToString);
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Zablokovani downloadPDF id ' + idDigiFile.ToString + ' pred zpracovanim');
|
|
|
|
|
|
url:= datMod.SQLGetString ('SELECT DocURL FROM ' + tblAPIDigiSoubory + ' WHERE ID=' + idDigiFile.ToString);
|
|
if (url<>'') then
|
|
begin
|
|
|
|
datMod.LogInfo (Quick.Logger.etInfo, 'Mam URL downloadPDF id ' + idDigiFile.ToString);
|
|
outData:= '';
|
|
|
|
if (sslLibPath='') then
|
|
begin
|
|
try
|
|
http1:= System.Net.HTTPClient.THTTPClient.Create;
|
|
datMod.LogInfo (Quick.Logger.etInfo, 'HTTP klient NET vytvoren downloadPDF id ' + idDigiFile.ToString);
|
|
aResp:= TMemoryStream.Create;
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Vytvoren memStream downloadPDF id ' + idDigiFile.ToString);
|
|
try
|
|
if (Assigned(http1)) then
|
|
begin
|
|
http1.AllowCookies:= false;
|
|
http1.UserAgent:= 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/144.0';
|
|
http1.Accept:= 'application/pdf';
|
|
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Nacitam data PDF pro downloadPDF id ' + idDigiFile.ToString);
|
|
iResp:= http1.Get (url);
|
|
aResp:= (iResp.ContentStream as TMemoryStream);
|
|
outData:= MemStreamToHex (aResp);
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Mam data PDF pro downloadPDF id ' + idDigiFile.ToString);
|
|
|
|
end;
|
|
except on E:Exception do
|
|
begin
|
|
sqlConnX.ExecSQL ('UPDATE ' + tblAPIDigiSoubory + ' SET Blokovano=0 WHERE ID=' + idDigiFile.ToString);
|
|
datMod.LogInfo (Quick.Logger.etError, 'Chyba downloadPDF id ' + idDigiFile.ToString + ' : ' + E.Message);
|
|
{$IFDEF DEBUG}
|
|
WriteLn ('Chyba downloadPDF id ' + idDigiFile.ToString + ' >> ' + E.Message);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
finally
|
|
http1.Free;
|
|
http1:= nil;
|
|
aResp.Free;
|
|
aResp:= nil;
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Uvolnen Net HTTP klient a memStream pro downloadPDF id ' + idDigiFile.ToString);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
IdOpenSSLSetLibPath (sslLibPath);
|
|
http2:= TIdHttp.Create (nil);
|
|
sslHndlr:= TIdSSLIOHandlerSocketOpenSSL.Create (http2);
|
|
respHttp2:= TMemoryStream.Create;
|
|
try
|
|
try
|
|
sslHndlr.SSLOptions.Method:= sslvTLSv1_2;
|
|
sslHndlr.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1];
|
|
http2.IOHandler:= sslHndlr;
|
|
|
|
http2.Request.Accept:= 'application/pdf';
|
|
http2.Request.BasicAuthentication := False;
|
|
http2.HTTPOptions:= http2.HTTPOptions + [hoKeepOrigProtocol] + [hoNoProtocolErrorException];
|
|
http2.Request.ContentType:= 'application/pdf; charset=utf-8';
|
|
http2.Get (url, respHttp2);
|
|
outData:= MemStreamToHex (respHttp2 as TMemoryStream);
|
|
except on E:Exception do
|
|
begin
|
|
sqlConnX.ExecSQL ('UPDATE ' + tblAPIDigiSoubory + ' SET Blokovano=0 WHERE ID=' + idDigiFile.ToString);
|
|
datMod.LogInfo (Quick.Logger.etError, 'Chyba downloadPDF (SSL) id ' + idDigiFile.ToString + ' : ' + E.Message + CRLF + url);
|
|
{$IFDEF DEBUG}
|
|
WriteLn ('Chyba downloadPDF (SSL) id ' + idDigiFile.ToString + ' >> ' + E.Message + CRLF + url);
|
|
{$ENDIF}
|
|
end;
|
|
end;
|
|
finally
|
|
FreeAndNil (sslHndlr); // must be freed before IdHttp
|
|
FreeAndNil (http2);
|
|
FreeAndNil (respHttp2);
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Uvolnen Indy HTTP klient a memStream pro downloadPDF id ' + idDigiFile.ToString);
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
if (outData<>'') then
|
|
begin
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Mam data 2 PDF pro downloadPDF id ' + idDigiFile.ToString);
|
|
fName:= '';
|
|
i:= LastDelimiter ('/\', url);
|
|
if (i>0) then
|
|
fName:= Copy (url, i+1, Length(url)-i);
|
|
|
|
if (LeftStr(outData,4)='5025') then
|
|
begin
|
|
outData2:= '';
|
|
for i:=1 to Length(outData) div 2 do
|
|
outData2:= outData2 + MidStr(outData, (4*i)-1, 2) + MidStr(outData, (4*i)-3, 2);
|
|
if (outData2<>'') then
|
|
outData:= outData2;
|
|
end;
|
|
|
|
lSQL:= 'DECLARE @i INT' + CRLF + 'SET @i=(SELECT ID FROM dbo.TabDokumenty WHERE JmenoACesta=N' + url.QuotedString
|
|
+ ')' + CRLF + 'IF (@i IS NULL)' + CRLF
|
|
+ ' BEGIN' + CRLF + ' INSERT dbo.TabDokumenty (Popis, JmenoACesta, Poznamka, Autor, Dokument) SELECT N' + fName.QuotedString
|
|
+ ', N' + fName.QuotedString + ', N' + url.QuotedString + ', N''apiImport'''
|
|
+ ', CONVERT(varbinary(max), 0x' + outData +', 1)' + CRLF + ' SET @i=SCOPE_IDENTITY()' + CRLF + ' END'
|
|
+ CRLF + 'SELECT @i';
|
|
sTemp:= datMod.SQLGetString (lSQL);
|
|
if (sTemp<>'') then
|
|
begin
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Update zapisu downloadPDF id ' + idDigiFile.ToString);
|
|
lSQL:= 'UPDATE ' + tblAPIDigiSoubory + ' SET IDDokument=' + sTemp + ', DatZpracovani=GETDATE(), Blokovano=0 WHERE ID=' + idDigiFile.ToString;
|
|
sqlConnX.ExecSQL(lSQL);
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Update zapisu/odblokovani downloadPDF id ' + idDigiFile.ToString + ' - OK');
|
|
end;
|
|
end;
|
|
|
|
end; // url<>''
|
|
|
|
|
|
if (url='') then
|
|
begin
|
|
lSQL:= 'UPDATE ' + tblAPIDigiSoubory + ' SET DatZpracovani=GETDATE(), Blokovano=0 WHERE ID=' + idDigiFile.ToString;
|
|
sqlConnX.ExecSQL (lSQL);
|
|
end;
|
|
|
|
|
|
except on E:Exception do
|
|
begin
|
|
sqlConnX.ExecSQL ('UPDATE ' + tblAPIDigiSoubory + ' SET Blokovano=0 WHERE ID=' + idDigiFile.ToString);
|
|
errMsg:= E.Message; // datMod.sqlQry11.FieldByName('ErrMsg').AsString;
|
|
{$IFDEF DEBUG}
|
|
WriteLn ('Chyba 2 zpracovani downloadPDF id ' + idDigiFile.ToString + ' >> ' + errMsg);
|
|
{$ENDIF}
|
|
// sqlConnX.ExecSQL('UPDATE ' + tblAPIDigiSoubory + ' SET PosledniChyba=N' + errMsg.QuotedString + ' WHERE ID=' + idDigiFile.ToString);
|
|
datMod.LogInfo(Quick.Logger.etError, 'Chyba 2 zpracovani downloadPDF ID ' + idDigiFile.ToString + ' : ' + errMsg);
|
|
end;
|
|
end;
|
|
end;
|
|
lQry.Next;
|
|
end; // while
|
|
end;
|
|
finally
|
|
lQry.Close;
|
|
FreeAndNil (lQry);
|
|
// lQry.Free;
|
|
// lQry:= nil;
|
|
end;
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Uzavrena SQL query - downloadPDF id ' + idDigiFile.ToString);
|
|
|
|
if (sqlConnX.InTransaction) then
|
|
sqlConnX.Commit;
|
|
inProg:= false;
|
|
end; // sql Connected
|
|
sqlConnX.Close;
|
|
FreeAndNil (sqlConnX);
|
|
// sqlConnX.Free;
|
|
// sqlConnX:= nil;
|
|
|
|
// datMod.LogInfo (Quick.Logger.etInfo, 'Zrusena SQL connection - downloadPDF id ' + idDigiFile.ToString);
|
|
end;
|
|
end;
|
|
|
|
except on E:Exception do
|
|
begin
|
|
inProg:= false;
|
|
if (lQry<>nil) then
|
|
begin
|
|
lQry.Close;
|
|
FreeAndNil (lQry);
|
|
end;
|
|
if (sqlConnX<>nil) then
|
|
begin
|
|
if (sqlConnX.InTransaction) then
|
|
sqlConnX.Rollback;
|
|
sqlConnX.Close;
|
|
FreeAndNil (sqlConnX);
|
|
// sqlConnX.Free;
|
|
// sqlConnX:= nil;
|
|
end;
|
|
errMsg:= E.Message; // datMod.sqlQry11.FieldByName('ErrMsg').AsString;
|
|
if (mamTabPrijataData) then
|
|
datMod.LogInfo (Quick.Logger.etError, 'Chyba zpracovani API souboru ID ' + idDigiFile.ToString + ' : ' + errMsg);
|
|
end;
|
|
end;
|
|
|
|
|
|
lLoop:= 0;
|
|
if (logRunCnt<5) then
|
|
Inc (logRunCnt);
|
|
end;
|
|
Inc (lLoop);
|
|
|
|
if (FTimer<>0) then
|
|
SetWaitableTimer (FTimer, TLargeInteger(liDueTime), 0, nil, nil, false);
|
|
repeat
|
|
lBusy:= MsgWaitForMultipleObjects (1, FTimer, false, INFINITE, QS_ALLINPUT);
|
|
until lBusy = WAIT_OBJECT_0;
|
|
// Sleep (998);
|
|
|
|
end;
|
|
finally
|
|
end;
|
|
|
|
end;
|
|
|
|
if (sqlConnX2<>nil) then
|
|
begin
|
|
if (sqlConnX2.Connected) then
|
|
sqlConnX2.Close;
|
|
FreeAndNil (sqlConnX2);
|
|
end;
|
|
|
|
end;
|
|
|
|
|