Base64 and text compression exchange between PB and SB

Share your advanced knowledge/code with the community.
Dirk Geppert
Posts: 330
Joined: Fri Sep 22, 2017 7:02 am

Base64 and text compression exchange between PB and SB

Post by Dirk Geppert »

Hi guys,

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
juror
Posts: 18
Joined: Fri Aug 01, 2014 4:39 am

Re: Base64 and text compression exchange between PB and SB

Post by juror »

Solved my base64 problem + other good information.

Thanks for sharing.

cheers

the top editorgadget does not display completely in w10 chrome. I'll keep looking at it.
Post Reply