if you ever plan to compress texts and encode them Base64 and the whole thing as a server (PB CGI) / client (SB WebApp) application.
There are a few things to consider so that the decoding works again.
For example, that the function *mem = Ascii (txt.s) extends the memory area by a NULL byte. I couldn't figure that out for ages
You can compile the following code with Spiderbasic and PureBasic, to see how the coding stuff works.
Maybe it will be helpful for someone and a safe storage for me

Update: bug fixes and switched to UTF-8
Code: Select all
EnableExplicit
CompilerIf #PB_Compiler_IsMainFile And #PB_Compiler_OS = #PB_OS_Web ; StringByteLength(str.s)
Procedure.i StringByteLength(str.s)
Protected n.i
! const encoder = new TextEncoder();
! const byteArray = encoder.encode(v_str);
! // Die Länge des Byte-Arrays entspricht der Anzahl der Bytes, die der String benötigt
! v_n = byteArray.length;
ProcedureReturn n
EndProcedure
CompilerEndIf
UseCRC32Fingerprint()
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
UseZipPacker()
CompilerEndIf
Procedure.s UnCompressStringBase64(txt.s)
Protected *out, size, unpacksize, *mem, Result.s, base64size, origSize
If Mid(txt, 1, 2) = "/+"
If Mid(txt, 11, 2) = "+/"
origSize = Val("$" + Mid(txt, 3, 8))
txt = Mid(txt, 13)
EndIf
EndIf
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
size = StringByteLength(txt)
CompilerElse
size = Len(txt)
CompilerEndIf
If size < 64
size = 64
EndIf
If size
*out = AllocateMemory(size * 2)
EndIf
Debug "Unmompress " + Str(Size) + " Bytes.." + " | Memorysize: " + Str(MemorySize(*out))
If *out
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
base64size = Base64Decoder(txt, *out, MemorySize(*out))
CompilerElse
base64size = Base64Decoder(txt, *out, 0, MemorySize(*out))
CompilerEndIf
Debug "Base64 Decoding Size: " + Str(base64size)
If base64size > 0
If origSize <> 0 ; string compression active
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
*mem = AllocateMemory(origSize)
If *mem
unpacksize = UncompressMemory(*out, base64size, *mem, MemorySize(*mem), #PB_PackerPlugin_Zip)
EndIf
Result = PeekS(*mem, unpacksize, #PB_UTF8)
CompilerElse
*mem = UncompressMemory(*out, 0, base64size)
unpacksize = MemorySize(*mem)
Result = PeekS(*mem, 0, unpacksize, #PB_UTF8)
CompilerEndIf
Debug "Uncompressing size: " + Str(unpacksize)
Else
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
Result = PeekS(*out, base64size, #PB_UTF8)
CompilerElse
Result = PeekS(*out, 0, base64size, #PB_UTF8)
CompilerEndIf
EndIf
EndIf
If *out
FreeMemory(*out)
EndIf
If *mem
FreeMemory(*mem)
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure.s CompressStringBase64 (txt.s, compress.i = #True)
Protected *mem, memSize, *out, outSize, base64size, Result.s, origSize, flags, compressedSize
origSize = StringByteLength(txt)
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
;{ == PureBasic ==
*mem = UTF8(txt) ; ! includes NULL at the end !
memSize = MemorySize(*mem) - 1
If compress
*out = AllocateMemory(MemorySize(*mem) * 2) ; Erhöht für Sicherheit
If *out
compressedSize = CompressMemory(*mem, memSize, *out, MemorySize(*out), #PB_PackerPlugin_Zip)
EndIf
FreeMemory(*mem)
*mem = *out
memSize = compressedSize
EndIf
;}
CompilerElse
; == SpiderBasic ==
If compress
; *mem = CompressString(txt)
; memSize = MemorySize(*mem)
; origSize = memSize
*mem = AllocateMemory(origSize)
memSize = origSize
If *mem
PokeS(*mem, 0, txt, origSize, #PB_String_NoZero | #PB_UTF8)
*out = CompressMemory(*mem, 0, memSize)
FreeMemory(*mem)
If *out
*mem = *out
memSize = MemorySize(*out)
EndIf
EndIf
Else
*mem = AllocateMemory(origSize)
memSize = origSize
If *mem
PokeS(*mem, 0, txt, origSize, #PB_String_NoZero | #PB_UTF8)
Debug PeekS(*mem, 0, origSize, #PB_UTF8)
Else
Debug "Memory Allocation error"
EndIf
EndIf
CompilerEndIf
If *mem
outSize = memSize * 2
If outSize < 64
outSize = 64
EndIf
*out = AllocateMemory(outSize)
If *out
If GetGadgetState(5)
flags | #PB_Cipher_NoPadding
EndIf
If GetGadgetState(6)
flags | #PB_Cipher_URL
EndIf
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
; == PureBasic ==
base64size = Base64EncoderBuffer(*mem, memSize, *out, outSize, flags)
Result = PeekS(*out, base64size, #PB_UTF8)
CompilerElse
; == SpiderBasic ==
base64size = Base64EncoderBuffer(*mem, 0, memSize, *out, 0, outSize, flags)
Result = PeekS(*out, 0, base64size, #PB_UTF8)
CompilerEndIf
FreeMemory(*out)
EndIf
FreeMemory(*mem)
EndIf
If Result <> "" And compress
Result = "/+" + RSet(Hex(origSize), 8, "0") + "+/" + Result
EndIf
Debug "Compressed: " + Result
SetGadgetText(3, "Origsize: " + Str(origSize) + " | Result: " + Str(Len(Result)) + " | Crc: " + StringFingerprint(Result, #PB_Cipher_CRC32))
ProcedureReturn Result
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Procedure DecodeTest ()
Protected decoded_txt.s, orig_txt.s, encoded_txt.s, txt.s
orig_txt = GetGadgetText(0)
encoded_txt = GetGadgetText(1)
decoded_txt = UnCompressStringBase64(encoded_txt)
encoded_txt = "CrC Check: " + StringFingerprint(orig_txt, #PB_Cipher_CRC32) + " vs " + StringFingerprint(decoded_txt, #PB_Cipher_CRC32)
If orig_txt <> decoded_txt
txt = "Error :-( " + encoded_txt
Else
txt = "It works! :-) " + encoded_txt
EndIf
txt + #CRLF$ + "Decoded: " + #CRLF$ + #CRLF$ + decoded_txt
SetGadgetText(1, txt)
EndProcedure
Procedure Encode()
Protected txt.s
txt = GetGadgetText(0)
If txt
SetGadgetText(1, CompressStringBase64(txt, GetGadgetState(2)))
EndIf
EndProcedure
Procedure Clipboard()
SetClipboardText(GetGadgetText(1))
EndProcedure
OpenWindow(0, 0, 0, 800, 840, "Base64/Compress Test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
If #PB_Compiler_OS = #PB_OS_Web
SetWindowTitle(0, GetWindowTitle(0) + " - SpiderBasic")
Else
SetWindowTitle(0, GetWindowTitle(0) + " - PureBasic")
EndIf
EditorGadget(0, 0, 0, 800, 380, #PB_Editor_WordWrap)
CheckBoxGadget(2, 10, 390, 150, 20, "StringCompression")
CheckBoxGadget(5, 170, 390, 180, 20, "#PB_Cipher_NoPadding")
CheckBoxGadget(6, 350, 390, 150, 20, "#PB_Cipher_URL ")
TextGadget(3, 500, 390, 300, 20, "")
EditorGadget(1, 0, 420, 800, 380, #PB_Editor_WordWrap)
ButtonGadget(4, 0, 810, 400, 30, "Copy to clipboard")
ButtonGadget(7, 400, 810, 400, 30, "Decode Test")
BindGadgetEvent(0, @Encode(), #PB_EventType_Change)
BindGadgetEvent(2, @Encode(), #PB_EventType_LeftClick)
BindGadgetEvent(5, @Encode(), #PB_EventType_LeftClick)
BindGadgetEvent(6, @Encode(), #PB_EventType_LeftClick)
BindGadgetEvent(4, @Clipboard(), #PB_EventType_LeftClick)
BindGadgetEvent(7, @DecodeTest(), #PB_EventType_LeftClick)
Define.s txt
txt = "Mo – Fr 09.00 – 17.00 Uhr\nSa, So und Feiertag 09.30" + #CRLF$ + #CRLF$ +
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " +
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, " +
"sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. " +
"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
SetGadgetText(0, txt)
Encode()
CompilerIf #PB_Compiler_OS <> #PB_OS_Web
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
CompilerEndIf
CompilerEndIf