diff --git a/baseunits/BaseCrypto.pas b/baseunits/BaseCrypto.pas index 036ecbcfb..21bab4ff9 100644 --- a/baseunits/BaseCrypto.pas +++ b/baseunits/BaseCrypto.pas @@ -5,7 +5,7 @@ interface uses - Classes, SysUtils, base64, DCPrijndael, DCPrc4, DCPsha256, DCPsha512, DCPmd5, Math; + Classes, SysUtils, base64, DCPrijndael, DCPsha256, DCPmd5, Math; function HexToStr(const h: String): String; procedure HexToBytes(const h: String; var o :TBytes); @@ -16,23 +16,11 @@ function StrToHexStr(const s: String): String; function Pkcs7AddPad(const s: String): String; function Pkcs7RemovePad(const s: String): String; -function AESEncryptCBCSHA256Base64Pkcs7(const s, key, iv: String): string; +function AESEncrpytCBCSHA256Base64Pkcs7(const s, key, iv: String): string; function AESDecryptCBCSHA256Base64Pkcs7(const s, key, iv: String): string; function AESDecryptCBCMD5Base64ZerosPadding(const s, key, iv: String): String; -function AESDecryptCBCHexBase64ZerosPadding(const s, key, iv: String): String; function MD5Hex(const s: String): String; -function AESEncryptCBC(const s, key, iv: String): String; function AESDecryptCBC(const s, key, iv: String): String; -function RC4(const s, key: String): String; - -function SHA256(const s: String): String; -function SHA256Hex(const s: String): String; -function HMAC_SHA256(const s, key: String): String; -function HMAC_SHA256Hex(const s, key: String): String; -function SHA512(const s: String): String; -function SHA512Hex(const s: String): String; -function HMAC_SHA512(const s, key: String): String; -function HMAC_SHA512Hex(const s, key: String): String; implementation @@ -101,31 +89,27 @@ function Pkcs7RemovePad(const s: String): String; SetLength(Result,Length(Result)-Ord(Result[Length(Result)])); end; -function AESEncryptCBCSHA256Base64Pkcs7(const s, key, iv: String): string; +function AESEncrpytCBCSHA256Base64Pkcs7(const s, key, iv: String): string; var i: String; ivb: TBytes; begin - Result := ''; - if (s = '') or (key = '') or (iv = '') then Exit; - + Result:=''; with TDCP_rijndael.Create(nil) do + begin try - try - InitStr(key, TDCP_sha256); - HexToBytes(iv, ivb); - SetIV(ivb[0]); - i := Pkcs7AddPad(s); - SetLength(Result, Length(i)); - EncryptCBC(i[1], Result[1], Length(i)); - Burn; - Result := EncodeStringBase64(Result); - except - Result := ''; - end; - finally - Free; + InitStr(key,TDCP_sha256); + HexToBytes(iv,ivb); + SetIV(ivb[0]); + i:=Pkcs7AddPad(s); + SetLength(Result,Length(i)); + EncryptCBC(i[1],Result[1],Length(i)); + Burn; + Result:=EncodeStringBase64(Result); + except end; + Free; + end; end; function AESDecryptCBCSHA256Base64Pkcs7(const s, key, iv: String): string; @@ -133,87 +117,45 @@ function AESDecryptCBCSHA256Base64Pkcs7(const s, key, iv: String): string; data: String; ivb: TBytes; begin - Result := ''; - if (s = '') or (key = '') or (iv = '') then Exit; - - with TDCP_rijndael.Create(nil) do - try - try - InitStr(key, TDCP_sha256); - HexToBytes(iv, ivb); - SetIV(ivb[0]); - data := DecodeStringBase64(s); - SetLength(Result, Length(data)); - DecryptCBC(data[1], Result[1], Length(data)); - Burn; - Result := Pkcs7RemovePad(Result); - except - Result := ''; - end; - finally - Free; - end; -end; - -function AESEncryptCBC(const s, key, iv: String): String; -var - ivBytes: array[0..15] of Byte; - keyBytes: TBytes; - i: Integer; -begin - Result := ''; - if (s = '') or (key = '') or (iv = '') then Exit; - - SetLength(keyBytes, Length(key)); - for i := 0 to Length(key) - 1 do - keyBytes[i] := Byte(key[i + 1]); - - FillChar(ivBytes, SizeOf(ivBytes), 0); - for i := 0 to Min(16, Length(iv)) - 1 do - ivBytes[i] := Byte(iv[i + 1]); - + Result:=''; with TDCP_rijndael.Create(nil) do + begin try - try - Init(keyBytes[0], Length(key) * 8, @ivBytes[0]); - SetLength(Result, Length(s)); - EncryptCBC(s[1], Result[1], Length(s)); - Burn; - except - Result := ''; - end; - finally - Free; + InitStr(key,TDCP_sha256); + HexToBytes(iv,ivb); + SetIV(ivb[0]); + data:=DecodeStringBase64(s); + SetLength(Result,Length(data)); + DecryptCBC(data[1],Result[1],Length(data)); + Burn; + Result:=Pkcs7RemovePad(Result); + except end; + Free; + end; end; function AESDecryptCBC(const s, key, iv: String): String; var - ivBytes: array[0..15] of Byte; + ivBytes: array[0 .. 15] of Byte; keyBytes: TBytes; i: Integer; begin Result := ''; - if (s = '') or (key = '') or (iv = '') then Exit; - SetLength(keyBytes, Length(key)); - for i := 0 to Length(key) - 1 do + for i := 0 to Length(key)-1 do keyBytes[i] := Byte(key[i + 1]); - FillChar(ivBytes, SizeOf(ivBytes), 0); + FillChar(ivBytes, 16, 0); for i := 0 to Min(16, Length(iv)) - 1 do ivBytes[i] := Byte(iv[i + 1]); with TDCP_rijndael.Create(nil) do try - try - Init(keyBytes[0], Length(key) * 8, @ivBytes[0]); - SetLength(Result, Length(s)); - DecryptCBC(s[1], Result[1], Length(s)); - Burn; - except - Result := ''; - end; + Init(keyBytes, Length(key) * 8, @ivBytes[0]); + SetLength(Result,Length(s)); + DecryptCBC(s[1],Result[1],Length(s)); + Burn; finally Free; end; @@ -221,48 +163,18 @@ function AESDecryptCBC(const s, key, iv: String): String; function AESDecryptCBCMD5Base64ZerosPadding(const s, key, iv: String): String; begin - if (s = '') or (key = '') or (iv = '') then Exit; - Result := AESDecryptCBC(DecodeStringBase64(s), MD5Hex(key), iv); end; -function AESDecryptCBCHexBase64ZerosPadding(const s, key, iv: String): String; -var - keyBytes, ivBytes: TBytes; - data: String; -begin - Result := ''; - if (s = '') or (key = '') or (iv = '') then Exit; - - HexToBytes(key, keyBytes); - HexToBytes(iv, ivBytes); - - with TDCP_rijndael.Create(nil) do - try - try - Init(keyBytes[0], Length(keyBytes) * 8, @ivBytes[0]); - data := DecodeStringBase64(s); - SetLength(Result, Length(data)); - DecryptCBC(data[1], Result[1], Length(data)); - Burn; - while (Length(Result) > 0) and (Result[Length(Result)] = #0) do - SetLength(Result, Length(Result) - 1); - except - Result := ''; - end; - finally - Free; - end; -end; - function MD5Hex(const s: String): String; var - h: array[0..15] of Byte; + h: TBytes; begin with TDCP_md5.Create(nil) do try Init; - Update(s[1], Length(s)); + UpdateStr(s); + SetLength(h, 16); Final(h); finally Free; @@ -270,182 +182,5 @@ function MD5Hex(const s: String): String; Result := LowerCase(StrToHexStr(BytesToString(h))); end; -function RC4(const s, key: String): String; -begin - Result := ''; - if (s = '') or (key = '') then Exit; - - SetLength(Result, Length(s)); - with TDCP_rc4.Create(nil) do - try - Init(key[1], Length(key) * 8, nil); - Encrypt(s[1], Result[1], Length(s)); - Burn; - finally - Free; - end; -end; - -function SHA256(const s: String): String; -var - digest: array[0..31] of Byte; -begin - with TDCP_sha256.Create(nil) do - try - Init; - Update(s[1], Length(s)); - Final(digest); - finally - Free; - end; - SetString(Result, PChar(@digest[0]), 32); -end; - -function SHA256Hex(const s: String): String; -begin - Result := LowerCase(StrToHexStr(SHA256(s))); -end; - -function HMAC_SHA256(const s, key: String): String; -const - BLOCK_SIZE = 64; -var - k: String; - ipad, opad: array[0..BLOCK_SIZE - 1] of Byte; - inner: array[0..31] of Byte; - outer: array[0..31] of Byte; - i: Integer; -begin - if (s = '') or (key = '') then Exit; - - if Length(key) > BLOCK_SIZE then - k := SHA256(key) - else - k := key; - - for i := 0 to BLOCK_SIZE - 1 do - begin - if i < Length(k) then - begin - ipad[i] := Byte(k[i + 1]) xor $36; - opad[i] := Byte(k[i + 1]) xor $5C; - end - else - begin - ipad[i] := $36; - opad[i] := $5C; - end; - end; - - with TDCP_sha256.Create(nil) do - try - Init; - Update(ipad[0], BLOCK_SIZE); - Update(s[1], Length(s)); - Final(inner); - finally - Free; - end; - - with TDCP_sha256.Create(nil) do - try - Init; - Update(opad[0], BLOCK_SIZE); - Update(inner[0], 32); - Final(outer); - finally - Free; - end; - - SetString(Result, PChar(@outer[0]), 32); -end; - -function HMAC_SHA256Hex(const s, key: String): String; -begin - if (s = '') or (key = '') then Exit; - - Result := LowerCase(StrToHexStr(HMAC_SHA256(s, key))); -end; - -function SHA512(const s: String): String; -var - digest: array[0..63] of Byte; -begin - with TDCP_sha512.Create(nil) do - try - Init; - Update(s[1], Length(s)); - Final(digest); - finally - Free; - end; - SetString(Result, PChar(@digest[0]), 64); -end; - -function SHA512Hex(const s: String): String; -begin - Result := LowerCase(StrToHexStr(SHA512(s))); -end; - -function HMAC_SHA512(const s, key: String): String; -const - BLOCK_SIZE = 128; -var - k: String; - ipad, opad: array[0..BLOCK_SIZE - 1] of Byte; - inner: array[0..63] of Byte; - outer: array[0..63] of Byte; - i: Integer; -begin - if (s = '') or (key = '') then Exit; - - if Length(key) > BLOCK_SIZE then - k := SHA512(key) - else - k := key; - - for i := 0 to BLOCK_SIZE - 1 do - begin - if i < Length(k) then - begin - ipad[i] := Byte(k[i + 1]) xor $36; - opad[i] := Byte(k[i + 1]) xor $5C; - end - else - begin - ipad[i] := $36; - opad[i] := $5C; - end; - end; - - with TDCP_sha512.Create(nil) do - try - Init; - Update(ipad[0], BLOCK_SIZE); - Update(s[1], Length(s)); - Final(inner); - finally - Free; - end; - - with TDCP_sha512.Create(nil) do - try - Init; - Update(opad[0], BLOCK_SIZE); - Update(inner[0], 64); - Final(outer); - finally - Free; - end; - - SetString(Result, PChar(@outer[0]), 64); -end; - -function HMAC_SHA512Hex(const s, key: String): String; -begin - if (s = '') or (key = '') then Exit; - - Result := LowerCase(StrToHexStr(HMAC_SHA512(s, key))); -end; +end. -end. \ No newline at end of file diff --git a/baseunits/ImagePuzzle.pas b/baseunits/ImagePuzzle.pas index f6687f526..1629dd1c2 100644 --- a/baseunits/ImagePuzzle.pas +++ b/baseunits/ImagePuzzle.pas @@ -23,7 +23,7 @@ TImagePuzzle = class implementation -uses Math, MemBitmap, webp; +uses Math; constructor TImagePuzzle.Create(horBlockCount, verBlockCount: Integer); var i: Integer; @@ -38,15 +38,9 @@ constructor TImagePuzzle.Create(horBlockCount, verBlockCount: Integer); procedure TImagePuzzle.DeScramble(input, output: TStream); var image, result: TPicture; - memStream: TMemoryStream; - tmpMemBitmap: TMemBitmap; - reversalMatrix: Boolean; - blockWidth, blockHeight: Double; - imgWidth, imgHeight: Integer; - baseBlockHeight, remainder: Integer; - destY, destH, srcY, srcH: Integer; + blockWidth, blockHeight: Extended; i, row, col: Integer; - x1, y1, x2, y2: Integer; + x1, y1: Integer; dstrect, srcrect: TRect; ext: String = 'jpg'; begin @@ -55,111 +49,39 @@ procedure TImagePuzzle.DeScramble(input, output: TStream); Assert(Length(Matrix) >= HorBlock * VerBlock, 'Invalid matrix size'); image := TPicture.Create; result := TPicture.Create; - memStream := TMemoryStream.Create; try - memStream.LoadFromStream(input); - memStream.Position := 0; - tmpMemBitmap := WebPToMemBitmap(memStream); - if Assigned(tmpMemBitmap) then - begin - try - ext := 'png'; - image.Bitmap.SetSize(tmpMemBitmap.Width, tmpMemBitmap.Height); - image.Bitmap.PixelFormat := pf32bit; - for i := 0 to tmpMemBitmap.Height - 1 do - begin - Move(tmpMemBitmap.ScanLine[i]^, image.Bitmap.ScanLine[i]^, tmpMemBitmap.Width * 4); - end; - finally - tmpMemBitmap.Free; - end; - end - else - begin - memStream.Position := 0; - image.LoadFromStream(memStream); - if image.Graphic is TPortableNetworkGraphic then - begin - ext := 'png'; - end; - end; + image.LoadFromStream(input); + if image.Graphic is TPortableNetworkGraphic then ext := 'png'; result.Bitmap.SetSize(image.Width, image.Height); - reversalMatrix := (HorBlock = 1) and (VerBlock > 0) and (Length(Matrix) >= VerBlock); - if reversalMatrix then - begin - for i := 0 to VerBlock - 1 do - begin - if Matrix[i] <> (VerBlock - 1 - i) then - begin - reversalMatrix := False; - Break; - end; - end; - end; - if reversalMatrix then - begin - imgHeight := image.Height; - imgWidth := image.Width; - baseBlockHeight := imgHeight div VerBlock; - remainder := imgHeight mod VerBlock; - for i := 0 to VerBlock - 1 do - begin - destH := baseBlockHeight; - destY := baseBlockHeight * i; - if i = 0 then - begin - destH := destH + remainder; - end - else - begin - destY := destY + remainder; - end; - dstrect := Rect(0, destY, imgWidth, destY + destH); - srcY := imgHeight - (baseBlockHeight * (i + 1)) - remainder; - srcH := destH; - srcrect := Rect(0, srcY, imgWidth, srcY + srcH); - result.Bitmap.Canvas.CopyRect(dstrect, image.Bitmap.Canvas, srcrect); - end; + if Multiply <= 1 then begin + blockWidth := float(image.Width) / HorBlock; + blockHeight := float(image.Height) / VerBlock; end - else - begin - if Multiply <= 1 then - begin - blockWidth := image.Width / HorBlock; - blockHeight := image.Height / VerBlock; - end - else - begin - blockWidth := Trunc(image.Width / (HorBlock * Multiply)) * Multiply; - blockHeight := Trunc(image.Height / (VerBlock * Multiply)) * Multiply; - end; - for i := 0 to HorBlock * VerBlock - 1 do - begin - row := Matrix[i] div HorBlock; - col := Matrix[i] mod HorBlock; - x1 := Trunc(col * blockWidth); - y1 := Trunc(row * blockHeight); - x2 := Trunc((col + 1) * blockWidth); - y2 := Trunc((row + 1) * blockHeight); - dstrect := Rect(x1, y1, x2, y2); - row := i div HorBlock; - col := i mod HorBlock; - x1 := Trunc(col * blockWidth); - y1 := Trunc(row * blockHeight); - x2 := Trunc((col + 1) * blockWidth); - y2 := Trunc((row + 1) * blockHeight); - srcrect := Rect(x1, y1, x2, y2); - result.Bitmap.Canvas.CopyRect(dstrect, image.Bitmap.Canvas, srcrect); - end; + else begin + blockWidth := trunc(float(image.Width) / (HorBlock * Multiply)) * Multiply; + blockHeight := trunc(float(image.Height) / (VerBlock * Multiply)) * Multiply; + end; + for i := 0 to HorBlock * VerBlock - 1 do begin + row := floor(float(Matrix[i]) / VerBlock); + col := Matrix[i] - row * HorBlock; + x1 := trunc(col * blockWidth); + y1 := trunc(row * blockHeight); + dstrect := Rect(x1, y1, Trunc(x1 + blockWidth), Trunc(y1 + blockHeight)); + row := floor(float(i) / HorBlock); + col := i - row * HorBlock; + x1 := trunc(col * blockWidth); + y1 := trunc(row * blockHeight); + srcrect := Rect(x1, y1, Trunc(x1 + blockWidth), Trunc(y1 + blockHeight)); + result.Bitmap.Canvas.CopyRect(dstrect, image.Bitmap.Canvas, srcrect); end; output.Position := 0; output.Size := 0; result.SaveToStreamWithFileExt(output, ext); finally - memStream.Free; result.Free; image.Free; end; end; -end. \ No newline at end of file +end. + diff --git a/baseunits/WebsiteModules.pas b/baseunits/WebsiteModules.pas index 50d33a9a3..a9a95e905 100644 --- a/baseunits/WebsiteModules.pas +++ b/baseunits/WebsiteModules.pas @@ -61,6 +61,10 @@ TModuleContainer = class; TOnAccountState = function(const AModule: TModuleContainer): Boolean; TOnCheckSite = function(const AModule: TModuleContainer): Boolean; + TOnDownloadArchive = function(const ATaskThread: TTaskThread; + const AURL: String; const ASavePath, ASaveFileName: String; + const AModule: TModuleContainer): Boolean; + TModuleMethod = (MMGetDirectoryPageNumber, MMGetNameAndLink, MMGetInfo, MMTaskStart, MMGetPageNumber, MMGetImageURL, MMBeforeDownloadImage, MMDownloadImage, MMSaveImage, MMAfterImageSaved, MMLogin); @@ -131,6 +135,7 @@ TModuleContainer = class InformationAvailable: Boolean; FavoriteAvailable: Boolean; DynamicPageLink: Boolean; + SupportArchiveDownloading: Boolean; TotalDirectoryPage: array of Integer; CurrentDirectoryIndex: Integer; MaxTaskLimit: Integer; @@ -151,6 +156,7 @@ TModuleContainer = class OnLogin: TOnLogin; OnAccountState: TOnAccountState; OnCheckSite: TOnCheckSite; + OnDownloadArchive: TOnDownloadArchive; constructor Create; destructor Destroy; override; public @@ -302,6 +308,7 @@ constructor TModuleContainer.Create; InformationAvailable := True; FavoriteAvailable := True; DynamicPageLink := False; + SupportArchiveDownloading := False; TotalDirectory := 1; CurrentDirectoryIndex := 0; FWebsiteBypass := TWebsiteBypass.Create(self); diff --git a/baseunits/lua/LuaCrypto.pas b/baseunits/lua/LuaCrypto.pas index 1e95a475d..bd2c29382 100644 --- a/baseunits/lua/LuaCrypto.pas +++ b/baseunits/lua/LuaCrypto.pas @@ -12,122 +12,57 @@ implementation uses LuaUtils, LuaPackage, BaseCrypto, synacode, uBaseUnit, htmlelements; -function GetLuaString(L: Plua_State; idx: Integer): String; -var - len: size_t; - p: PChar; -begin - p := luaL_checklstring(L, idx, @len); - SetString(Result, p, len); -end; - -procedure PushLuaString(L: Plua_State; const s: String); -begin - if s <> '' then - lua_pushlstring(L, PChar(s), Length(s)) - else - lua_pushliteral(L, ''); -end; - function crypto_hextostr(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, HexToStr(GetLuaString(L, 1))); + lua_pushstring(L, HexToStr(luaToString(L, 1))); Result := 1; end; function crypto_strtohexstr(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, StrToHexStr(GetLuaString(L, 1))); + lua_pushstring(L, StrToHexStr(luaToString(L, 1))); Result := 1; end; function crypto_md5hex(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, MD5Hex(GetLuaString(L, 1))); - Result := 1; -end; - -function crypto_sha256hex(L: Plua_State): Integer; cdecl; -begin - lua_pushstring(L, SHA256Hex(GetLuaString(L, 1))); - Result := 1; -end; - -function crypto_sha512hex(L: Plua_State): Integer; cdecl; -begin - lua_pushstring(L, SHA512Hex(GetLuaString(L, 1))); - Result := 1; -end; - -function crypto_hmac_sha256hex(L: Plua_State): Integer; cdecl; -begin - lua_pushstring(L, HMAC_SHA256Hex(GetLuaString(L, 1), GetLuaString(L, 2))); - Result := 1; -end; - -function crypto_hmac_sha512hex(L: Plua_State): Integer; cdecl; -begin - lua_pushstring(L, HMAC_SHA512Hex(GetLuaString(L, 1), GetLuaString(L, 2))); - Result := 1; -end; - -function crypto_aesencryptcbc(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, AESEncryptCBC(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); + lua_pushstring(L, MD5Hex(luaToString(L, 1))); Result := 1; end; function crypto_aesdecryptcbc(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, AESDecryptCBC(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); - Result := 1; -end; - -function crypto_AESEncryptCBCSHA256Base64Pkcs7(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, AESEncryptCBCSHA256Base64Pkcs7(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); + lua_pushstring(L, AESDecryptCBC(luaToString(L, 1), luaToString(L, 2), luaToString(L, 3))); Result := 1; end; function crypto_AESDecryptCBCSHA256Base64Pkcs7(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, AESDecryptCBCSHA256Base64Pkcs7(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); - Result := 1; -end; - -function crypto_AESDecryptCBCMD5Base64ZerosPadding(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, AESDecryptCBCMD5Base64ZerosPadding(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); - Result := 1; -end; - -function crypto_AESDecryptCBCHexBase64ZerosPadding(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, AESDecryptCBCHexBase64ZerosPadding(GetLuaString(L, 1), GetLuaString(L, 2), GetLuaString(L, 3))); + lua_pushstring(L, AESDecryptCBCSHA256Base64Pkcs7(luaToString(L, 1), luaToString(L, 2), luaToString(L, 3))); Result := 1; end; function lua_encryptstring(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, EncryptString(GetLuaString(L, 1))); + lua_pushstring(L, EncryptString(luaToString(L, 1))); Result := 1; end; function lua_decryptstring(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, DecryptString(GetLuaString(L, 1))); + lua_pushstring(L, DecryptString(luaToString(L, 1))); Result := 1; end; function lua_htmldecode(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, HTMLDecode(GetLuaString(L, 1))); + lua_pushstring(L, HTMLDecode(luaToString(L, 1))); Result := 1; end; function lua_htmlencode(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, EscapeHTML(GetLuaString(L, 1))); + lua_pushstring(L, EscapeHTML(luaToString(L, 1))); Result := 1; end; @@ -135,132 +70,102 @@ function lua_htmlencode(L: Plua_State): Integer; cdecl; function lua_decodeurl(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, DecodeURL(GetLuaString(L, 1))); + lua_pushstring(L, DecodeURL(luaToString(L, 1))); Result := 1; end; function lua_encodeurl(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, EncodeURL(GetLuaString(L, 1))); + lua_pushstring(L, EncodeURL(luaToString(L, 1))); Result := 1; end; function lua_decodeuu(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, DecodeUU(GetLuaString(L, 1))); + lua_pushstring(L, DecodeUU(luaToString(L, 1))); Result := 1; end; function lua_encodeuu(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, EncodeUU(GetLuaString(L, 1))); + lua_pushstring(L, EncodeUU(luaToString(L, 1))); Result := 1; end; function lua_encodeurlelement(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, EncodeURLElement(GetLuaString(L, 1))); + lua_pushstring(L, EncodeURLElement(luaToString(L, 1))); Result := 1; end; function lua_decodebase64(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, DecodeBase64(GetLuaString(L, 1))); + lua_pushstring(L, DecodeBase64(luaToString(L, 1))); Result := 1; end; function lua_encodebase64(L: Plua_State): Integer; cdecl; begin - lua_pushstring(L, EncodeBase64(GetLuaString(L, 1))); + lua_pushstring(L, EncodeBase64(luaToString(L, 1))); Result := 1; end; function lua_crc16(L: Plua_State): Integer; cdecl; begin - lua_pushinteger(L, Crc16(GetLuaString(L, 1))); + lua_pushinteger(L, Crc16(luaToString(L, 1))); Result := 1; end; function lua_crc32(L: Plua_State): Integer; cdecl; begin - lua_pushinteger(L, Crc32(GetLuaString(L, 1))); + lua_pushinteger(L, Crc32(luaToString(L, 1))); Result := 1; end; function lua_md4(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, MD4(GetLuaString(L, 1))); + lua_pushstring(L, MD4(luaToString(L, 1))); Result := 1; end; function lua_md5(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, MD5(GetLuaString(L, 1))); + lua_pushstring(L, MD5(luaToString(L, 1))); Result := 1; end; function lua_hmac_md5(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, HMAC_MD5(GetLuaString(L, 1), GetLuaString(L, 2))); + lua_pushstring(L, HMAC_MD5(luaToString(L, 1), luaToString(L, 2))); Result := 1; end; function lua_md5longhash(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, MD5LongHash(GetLuaString(L, 1), lua_tointeger(L, 2))); + lua_pushstring(L, MD5LongHash(luaToString(L, 1), lua_tointeger(L, 2))); Result := 1; end; function lua_sha1(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, SHA1(GetLuaString(L, 1))); + lua_pushstring(L, SHA1(luaToString(L, 1))); Result := 1; end; function lua_hmac_sha1(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, HMAC_SHA1(GetLuaString(L, 1), GetLuaString(L, 2))); + lua_pushstring(L, HMAC_SHA1(luaToString(L, 1), luaToString(L, 2))); Result := 1; end; function lua_sha1longhash(L: Plua_State): Integer; cdecl; begin - PushLuaString(L, SHA1LongHash(GetLuaString(L, 1), lua_tointeger(L, 2))); - Result := 1; -end; - -function crypto_sha256(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, SHA256(GetLuaString(L, 1))); - Result := 1; -end; - -function crypto_hmac_sha256(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, HMAC_SHA256(GetLuaString(L, 1), GetLuaString(L, 2))); - Result := 1; -end; - -function crypto_sha512(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, SHA512(GetLuaString(L, 1))); - Result := 1; -end; - -function crypto_hmac_sha512(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, HMAC_SHA512(GetLuaString(L, 1), GetLuaString(L, 2))); - Result := 1; -end; - -function crypto_rc4(L: Plua_State): Integer; cdecl; -begin - PushLuaString(L, RC4(GetLuaString(L, 1), GetLuaString(L, 2))); + lua_pushstring(L, SHA1LongHash(luaToString(L, 1), lua_tointeger(L, 2))); Result := 1; end; const - cryptomethods: packed array [0..22] of luaL_Reg = ( + cryptomethods: packed array [0..9] of luaL_Reg = ( (name: 'EncryptString'; func: @lua_encryptstring), (name: 'DecryptString'; func: @lua_decryptstring), (name: 'HTMLDecode'; func: @lua_htmldecode), @@ -268,21 +173,8 @@ function crypto_rc4(L: Plua_State): Integer; cdecl; (name: 'HexToStr'; func: @crypto_hextostr), (name: 'StrToHexStr'; func: @crypto_strtohexstr), (name: 'MD5Hex'; func: @crypto_md5hex), - (name: 'SHA256'; func: @crypto_sha256), - (name: 'SHA512'; func: @crypto_sha512), - (name: 'SHA256Hex'; func: @crypto_sha256hex), - (name: 'SHA512Hex'; func: @crypto_sha512hex), - (name: 'HMAC_SHA256'; func: @crypto_hmac_sha256), - (name: 'HMAC_SHA512'; func: @crypto_hmac_sha512), - (name: 'HMAC_SHA256Hex'; func: @crypto_hmac_sha256hex), - (name: 'HMAC_SHA512Hex'; func: @crypto_hmac_sha512hex), - (name: 'AESEncryptCBC'; func: @crypto_aesencryptcbc), (name: 'AESDecryptCBC'; func: @crypto_aesdecryptcbc), - (name: 'AESEncryptCBCSHA256Base64Pkcs7'; func: @crypto_AESEncryptCBCSHA256Base64Pkcs7), (name: 'AESDecryptCBCSHA256Base64Pkcs7'; func: @crypto_AESDecryptCBCSHA256Base64Pkcs7), - (name: 'AESDecryptCBCMD5Base64ZerosPadding'; func: @crypto_AESDecryptCBCMD5Base64ZerosPadding), - (name: 'AESDecryptCBCHexBase64ZerosPadding'; func: @crypto_AESDecryptCBCHexBase64ZerosPadding), - (name: 'RC4'; func: @crypto_rc4), (name: nil; func: nil) ); @@ -315,4 +207,5 @@ function luaopen_crypto(L: Plua_State): Integer; cdecl; initialization LuaPackage.AddLib('crypto', @luaopen_crypto); -end. \ No newline at end of file +end. + diff --git a/baseunits/lua/LuaWebsiteModules.pas b/baseunits/lua/LuaWebsiteModules.pas index c5183c06e..79645851a 100644 --- a/baseunits/lua/LuaWebsiteModules.pas +++ b/baseunits/lua/LuaWebsiteModules.pas @@ -31,6 +31,7 @@ TLuaWebsiteModule = class OnLogin: String; OnAccountState: String; OnCheckSite: String; + OnDownloadArchive: String; Storage: TStringsStorage; LastUpdated: String; Container: TLuaWebsiteModulesContainer; @@ -464,6 +465,29 @@ function DoCheckSite(const AModule: TModuleContainer): Boolean; end; end; +function DoDownloadArchive(const ATaskThread: TTaskThread; const AURL: String; + const ASavePath, ASaveFileName: String; const AModule: TModuleContainer): Boolean; +var + L: TLuaWebsiteModuleHandler; +begin + Result := False; + with TLuaWebsiteModule(AModule.LuaModule) do + try + L := GetLuaWebsiteModuleHandler(AModule); + L.LoadObject('TASK', ATaskThread.Container, @luaDownloadTaskMetaTable); + L.LoadObject('HTTP', ATaskThread.HTTP, @luaHTTPSendThreadAddMetaTable); + luaPushStringGlobal(L.Handle, 'URL', AURL); + luaPushStringGlobal(L.Handle, 'PATH', ASavePath); + luaPushStringGlobal(L.Handle, 'FILENAME', ASaveFileName); + + L.CallFunction(OnDownloadArchive); + Result := lua_toboolean(L.Handle, -1); + except + on E: Exception do + SendLogException('LUA>DoDownloadArchive("' + ExtractFileName(Container.FileName) + '")>', E); + end; +end; + function _newwebsitemodule(L: Plua_State): Integer; cdecl; begin luaClassPushObject(L, TLuaWebsiteModule.Create, '', False, @luaWebsiteModuleAddMetaTable); @@ -581,6 +605,8 @@ procedure TLuaWebsiteModulesLoaderThread.LoadLuaWebsiteModule( Module.OnAccountState := @DoAccountState; if OnCheckSite <> '' then Module.OnCheckSite := @DoCheckSite; + if OnDownloadArchive <> '' then + Module.OnDownloadArchive := @DoDownloadArchive; end; finally Modules.Unlock; @@ -1024,6 +1050,8 @@ procedure luaWebsiteModuleAddMetaTable(const L: Plua_State; const Obj: Pointer; luaClassAddStringProperty(L, MetaTable, 'LastUpdated', @LastUpdated); luaClassAddIntegerProperty(L, MetaTable, 'CurrentDirectoryIndex', @Module.CurrentDirectoryIndex); luaClassAddStringProperty(L, MetaTable, 'OnCheckSite', @OnCheckSite); + luaClassAddBooleanProperty(L, MetaTable, 'SupportArchiveDownloading', @Module.SupportArchiveDownloading); + luaClassAddStringProperty(L, MetaTable, 'OnDownloadArchive', @OnDownloadArchive); luaClassAddProperty(L, MetaTable, UserData, 'TotalDirectory', @lua_gettotaldirectory, @lua_settotaldirectory); luaClassAddProperty(L, MetaTable, UserData, 'AccountSupport', @lua_getaccountsupport, @lua_setaccountsupport); diff --git a/baseunits/uBaseUnit.pas b/baseunits/uBaseUnit.pas index 06378cb31..8f2e8b838 100644 --- a/baseunits/uBaseUnit.pas +++ b/baseunits/uBaseUnit.pas @@ -233,6 +233,7 @@ interface MangaInfo_StatusCancelled = '3'; FMDSupportedPackedOutputExt: array[0..3] of ShortString = ('.zip', '.cbz', '.pdf', '.epub'); + FMDSupportedArchiveExt: array[0..5] of ShortString = ('.zip', '.cbz', '.rar', '.cbr', '.7z', '.tar'); {$ifdef windows} // MAX_PATH = 260 // MAX_PATH - 12 - 1 diff --git a/baseunits/uDownloadsManager.pas b/baseunits/uDownloadsManager.pas index 11fb43229..00e709d9a 100644 --- a/baseunits/uDownloadsManager.pas +++ b/baseunits/uDownloadsManager.pas @@ -87,6 +87,7 @@ TTaskThread = class(TBaseThread) procedure Execute; override; function Compress: Boolean; function Convert: Boolean; + function DownloadArchive: Boolean; procedure SyncStop; procedure StatusFailedToCreateDir; function FirstFailedChapters: Integer; @@ -738,6 +739,72 @@ function TTaskThread.Convert: Boolean; end; end; +function TTaskThread.DownloadArchive: Boolean; +var + SavePath, ArchiveFileName, ArchiveURL: String; + i: Integer; + FileExt: String; + AllSuccess: Boolean; +begin + Result := False; + + SavePath := CorrectPathSys(Container.DownloadInfo.SaveTo); + if not ForceDirectories(SavePath) then + begin + StatusFailedToCreateDir; + Exit(False); + end; + + ArchiveFileName := Container.ChapterNames[Container.CurrentDownloadChapterPtr]; + AllSuccess := True; + + for i := 0 to Container.PageLinks.Count - 1 do + begin + ArchiveURL := Trim(Container.PageLinks[i]); + if (ArchiveURL = '') or (ArchiveURL = 'D') then + Continue; + + if Assigned(TModuleContainer(Container.DownloadInfo.Module).OnDownloadArchive) then + begin + if not TModuleContainer(Container.DownloadInfo.Module).OnDownloadArchive( + Self, + ArchiveURL, + SavePath, + ArchiveFileName, + TModuleContainer(Container.DownloadInfo.Module)) then + begin + AllSuccess := False; + end; + end + else + begin + AllSuccess := False; + end; + + if AllSuccess then + begin + Container.PageLinks[i] := 'D'; + InterLockedIncrement(Container.DownCounter); + Container.DownloadInfo.Progress := + Format('%d/%d', [Container.DownCounter, Container.PageNumber]); + end; + end; + + if AllSuccess then + begin + for i := Low(FMDSupportedArchiveExt) to High(FMDSupportedArchiveExt) do + begin + FileExt := FMDSupportedArchiveExt[i]; + if FileExists(SavePath + ArchiveFileName + FileExt) then + begin + Exit(True); + end; + end; + end; + + Result := False; +end; + procedure TTaskThread.SyncStop; begin Container.Manager.CheckAndActiveTask(FCheckAndActiveTaskFlag); @@ -1029,6 +1096,24 @@ procedure TTaskThread.Execute; end; end; + function CheckForArchiveExists: Boolean; + var + i: Integer; + ArchivePath, ArchiveName: String; + begin + Result := False; + ArchivePath := CorrectPathSys(Container.DownloadInfo.SaveTo); + ArchiveName := Container.ChapterNames[Container.CurrentDownloadChapterPtr]; + for i := Low(FMDSupportedArchiveExt) to High(FMDSupportedArchiveExt) do + begin + if FileExists(ArchivePath + ArchiveName + FMDSupportedArchiveExt[i]) then + begin + Result := True; + Exit; + end; + end; + end; + function CheckForExists: Integer; var FileExists: Boolean; @@ -1171,7 +1256,11 @@ procedure TTaskThread.Execute; end; //check path - if OptionGenerateChapterFolder then + if TModuleContainer(Container.DownloadInfo.Module).SupportArchiveDownloading then + begin + CurrentWorkingDir := CorrectPathSys(Container.DownloadInfo.SaveTo); + end + else if OptionGenerateChapterFolder then begin CurrentWorkingDir := CorrectPathSys(Container.DownloadInfo.SaveTo) + Container.ChapterNames[Container.CurrentDownloadChapterPtr]; @@ -1231,103 +1320,139 @@ procedure TTaskThread.Execute; end; end; - // Check files, if exist set mark 'D', otherwise 'W' or 'G' for dynamic image url - CheckForExists; - - // Get the real image urls - if Container.PageLinks.Count = 0 then + // Archive download mode + if TModuleContainer(Container.DownloadInfo.Module).SupportArchiveDownloading then begin - Container.PageLinks.Add('W'); - end; - Container.PageNumber := Container.PageLinks.Count; - if (not DynamicPageLink) and CheckForPrepare then + if CheckForArchiveExists then + begin + Container.DownloadInfo.Progress := ''; + Container.Status := STATUS_FINISH; + end + else + begin + Container.WorkCounter := 0; + Container.DownCounter := 0; + Container.DownloadInfo.iProgress := 0; + Container.DownloadInfo.Progress := + Format('%d/%d', [Container.DownCounter, Container.PageNumber]); + Container.DownloadInfo.Status := + Format('[%d/%d] %s (%s)', + [Container.CurrentDownloadChapterPtr + 1, + Container.ChapterLinks.Count, + RS_Downloading, + Container.ChapterNames[Container.CurrentDownloadChapterPtr]]); + Container.Status := STATUS_DOWNLOAD; + + if DownloadArchive then + begin + Container.DownloadInfo.Progress := ''; + Container.Status := STATUS_FINISH; + end + else + begin + Container.Status := STATUS_FAILED; + end; + end; + end + else begin - Flag := CS_GETPAGELINK; - Container.WorkCounter := 0; - Container.DownCounter := 0; - Container.DownloadInfo.iProgress := 0; - Container.DownloadInfo.Progress := - Format('%d/%d', [Container.DownCounter, Container.PageNumber]); - Container.DownloadInfo.Status := - Format('[%d/%d] %s (%s)', - [Container.CurrentDownloadChapterPtr + 1, - Container.ChapterLinks.Count, - RS_Preparing, - Container.ChapterNames[Container.CurrentDownloadChapterPtr]]); - Container.Status := STATUS_PREPARE; + // Check files, if exist set mark 'D', otherwise 'W' or 'G' for dynamic image url + CheckForExists; - Checkout; - if Terminated then + // Get the real image urls + if Container.PageLinks.Count = 0 then begin - Exit; + Container.PageLinks.Add('W'); end; - - //check if pagelink is found. Else set again to 'W'(some script return '') - if Container.PageLinks.Count > 0 then + Container.PageNumber := Container.PageLinks.Count; + if (not DynamicPageLink) and CheckForPrepare then begin - for i := 0 to Container.PageLinks.Count - 1 do + Flag := CS_GETPAGELINK; + Container.WorkCounter := 0; + Container.DownCounter := 0; + Container.DownloadInfo.iProgress := 0; + Container.DownloadInfo.Progress := + Format('%d/%d', [Container.DownCounter, Container.PageNumber]); + Container.DownloadInfo.Status := + Format('[%d/%d] %s (%s)', + [Container.CurrentDownloadChapterPtr + 1, + Container.ChapterLinks.Count, + RS_Preparing, + Container.ChapterNames[Container.CurrentDownloadChapterPtr]]); + Container.Status := STATUS_PREPARE; + + Checkout; + if Terminated then begin - if Trim(Container.PageLinks[i]) = '' then + Exit; + end; + + //check if pagelink is found. Else set again to 'W'(some script return '') + if Container.PageLinks.Count > 0 then + begin + for i := 0 to Container.PageLinks.Count - 1 do begin - Container.PageLinks[i] := 'W'; + if Trim(Container.PageLinks[i]) = '' then + begin + Container.PageLinks[i] := 'W'; + end; end; end; end; - end; - if Terminated then Exit; + if Terminated then Exit; - // download the images - // If Container doesn't have any image, we will skip the loop. Otherwise - // download them - Container.PageNumber := Container.PageLinks.Count; - if Container.PageLinks.Count > 0 then - begin - Flag := CS_DOWNLOAD; - Container.WorkCounter := 0; - Container.DownCounter := 0; - Container.DownloadInfo.iProgress := 0; - Container.DownloadInfo.Progress := - Format('%d/%d', [Container.DownCounter, Container.PageNumber]); - Container.DownloadInfo.Status := - Format('[%d/%d] %s (%s)', - [Container.CurrentDownloadChapterPtr + 1, - Container.ChapterLinks.Count, - RS_Downloading, - Container.ChapterNames[Container.CurrentDownloadChapterPtr]]); - Container.Status := STATUS_DOWNLOAD; - - Checkout; - if Terminated then - begin - Exit; - end; - - //check if all page is downloaded - if CheckForFinish then + // download the images + // If Container doesn't have any image, we will skip the loop. Otherwise + // download them + Container.PageNumber := Container.PageLinks.Count; + if Container.PageLinks.Count > 0 then begin - Container.DownloadInfo.Progress := ''; - Container.Status := STATUS_CONVERT; - if not Convert then + Flag := CS_DOWNLOAD; + Container.WorkCounter := 0; + Container.DownCounter := 0; + Container.DownloadInfo.iProgress := 0; + Container.DownloadInfo.Progress := + Format('%d/%d', [Container.DownCounter, Container.PageNumber]); + Container.DownloadInfo.Status := + Format('[%d/%d] %s (%s)', + [Container.CurrentDownloadChapterPtr + 1, + Container.ChapterLinks.Count, + RS_Downloading, + Container.ChapterNames[Container.CurrentDownloadChapterPtr]]); + Container.Status := STATUS_DOWNLOAD; + + Checkout; + if Terminated then begin - Container.Status := STATUS_FAILED; + Exit; end; - if Container.Status <> STATUS_FAILED then + //check if all page is downloaded + if CheckForFinish then begin Container.DownloadInfo.Progress := ''; - Container.Status := STATUS_COMPRESS; - if not Compress then + Container.Status := STATUS_CONVERT; + if not Convert then begin Container.Status := STATUS_FAILED; end; + + if Container.Status <> STATUS_FAILED then + begin + Container.DownloadInfo.Progress := ''; + Container.Status := STATUS_COMPRESS; + if not Compress then + begin + Container.Status := STATUS_FAILED; + end; + end; + end + else + begin + Container.Status := STATUS_FAILED; end; end else - begin - Container.Status := STATUS_FAILED; - end; - end - else begin Logger.SendWarning(Format('%s, pagelinks is empty. "%s" "%s" "%s"', [Self.ClassName, @@ -1337,6 +1462,7 @@ procedure TTaskThread.Execute; ])); Container.Status := STATUS_FAILED; end; + end; if Container.Status = STATUS_FAILED then begin @@ -1366,9 +1492,12 @@ procedure TTaskThread.Execute; end; end; - if IsDirectoryEmpty(CurrentWorkingDir) then + if not TModuleContainer(Container.DownloadInfo.Module).SupportArchiveDownloading then begin - RemoveDir(CurrentWorkingDir); + if IsDirectoryEmpty(CurrentWorkingDir) then + begin + RemoveDir(CurrentWorkingDir); + end; end; end;