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(i).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 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/134.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 datMod.LogInfo (Quick.Logger.etError, 'Chyba zpracovani downloadPDF id ' + idDigiFile.ToString + ' : ' + E.Message); {$IFDEF DEBUG} WriteLn ('Chyba zpracovani 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); 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'; respHttp2:= TMemoryStream.Create; http2.Get (url, respHttp2); outData:= MemStreamToHex (respHttp2 as TMemoryStream); 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 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; 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;