FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour hb_base64encode() stays empty
Posts: 179
Joined: Fri Dec 07, 2007 01:26 PM
hb_base64encode() stays empty
Posted: Wed May 15, 2024 09:50 AM
Dear friends,

please could you be so kind as to help me out.

Here is a small piece of code that on my systems does not produce output for hb_base64encode()

Code (fw): Select all Collapse
// C:\FWH\SAMPLES\RUTHBASE64.PRG

#include "FiveWin.ch"
#Include "Outlook.ch"
#Include "Mail.ch"


FUNCTION Main()

  LOCAL cImgPath, cImgBase64, cImgMemo
  
  cImgPath     := "c:\fwh\samples\img\start_slide1.jpg"
  cImgMemo     := MEMOREAD(cImgPath)
  cImgBase64   := hb_base64encode(MEMOREAD(cImgPath))
 
? "cImgPath", cImgPath
? "cImgMemo", cImgMemo
? "cImgBase64", cImgBase64

RETURN NIL
What is causing me a headache is that the hb_base64encode() produces output perfectly in my mod_harbour code. Please may I provide this too.


Code (fw): Select all Collapse
#include "c:\harbour\contrib\hbcurl\hbcurl.ch"
#define HB_CURLOPT_POST                      47
#define HB_CURLOPT_URL                        2
#define HB_CURLOPT_DL_BUFF_SETUP              1008
#define HB_CURLOPT_POSTFIELDS                 15
#define HB_CURLOPT_WRITEFUNCTION              11

FUNCTION Main()
    LOCAL cToken, cResult
 cToken := GetAccessToken()
  IF !EMPTY(cToken)
  cResult := SendEmail(cToken)
    ?"Email Send Result: ", cResult
  ELSE
    ? "Failed to retrieve access token."
  ENDIF
 

    
FUNCTION GetAccessToken()
    LOCAL hCurl := CURL_easy_init()
    LOCAL cPayload := ""
    LOCAL cToken := ""
    LOCAL cTest := ""
    LOCAL nStartPos, nEndPos
    LOCAL aHeaders := {"Content-Type: application/x-www-form-urlencoded"}
    LOCAL cTenantID := hb_GetEnv("TENANT_ID")
    LOCAL cClientId := hb_GetEnv("365client_id")
    LOCAL cClientSecret := hb_GetEnv("365client_secret")
    IF hCurl != NIL
        CURL_easy_setopt(hCurl, HB_CURLOPT_URL, "https://login.microsoftonline.com/"+cTenantID+"/oauth2/v2.0/token")
        CURL_easy_setopt(hCurl, HB_CURLOPT_HTTPHEADER, aHeaders)
        CURL_easy_setopt(hCurl, HB_CURLOPT_POSTFIELDS, "grant_type=client_credentials&client_id="+cClientId+"&client_secret="+cClientSecret+"&scope=https://graph.microsoft.com/.default")
        CURL_easy_setopt(hCurl, HB_CURLOPT_POST, .T.)
        curl_easy_setopt( hCurl, HB_CURLOPT_DL_BUFF_SETUP )
        CURL_easy_setopt(hCurl, HB_CURLOPT_WRITEFUNCTION, @cPayload) // Buffer the response
        
        
        CURL_easy_perform(hCurl)
        cPayload := curl_easy_dl_buff_get(hCurl) // Get the response from the buffer
        nStartPos := AT('"access_token":"',cPayload)+LEN('"access_token":"')
        nEndPos := hb_AT('"', cPayload, nStartPos)
        cToken := SUBSTR(cPayload, nStartPos, nEndPos - nStartPos)
      

        CURL_easy_cleanup(hCurl)

       
    ELSE
        ? "Failed to initialize cURL session."
    ENDIF

    RETURN cToken


    FUNCTION SendEmail(cToken)
        LOCAL hCurl := CURL_easy_init()
        LOCAL cEmailJson 
        LOCAL cResponse := ""
        LOCAL aHeaders := {}
        LOCAL cImgBase64 := ""

cImgBase64 := hb_base64Encode(hb_MemoRead("c:\www\htdocs\submarine_yellow\img\latest_news2.jpg"))
? "cImgBase64", cImgBase64
        cEmailJson := '{"message": {"subject": "Test base64", ';
        + '"body": {"contentType": "html", ';
        + '"content": "<h1>test</h1><p>The new cafeteria is open...</p>';
        + '<img src=\"data:image/jpeg;base64,' + cImgBase64 + '\" > ';
        + '"}, ';
        + '"toRecipients": [{"emailAddress": {"address": "testrecip@****.info"}}]}, ';
        + '"saveToSentItems": "true"}'
       
        IF hCurl != NIL

            AADD(aHeaders, "Authorization: Bearer " + cToken)
            AADD(aHeaders, "Content-Type: application/json")


            CURL_easy_setopt(hCurl, HB_CURLOPT_URL, "https://graph.microsoft.com/v1.0/users/test@*****.at/sendMail")
            CURL_easy_setopt(hCurl, HB_CURLOPT_HTTPHEADER, aHeaders)
            CURL_easy_setopt(hCurl, HB_CURLOPT_POSTFIELDS, cEmailJson)
            CURL_easy_setopt(hCurl, HB_CURLOPT_POST, .T.)
            CURL_easy_setopt(hCurl, HB_CURLOPT_WRITEFUNCTION, @cResponse) // Buffer the response
    
            CURL_easy_perform(hCurl)
            cResponse := curl_easy_dl_buff_get(hCurl) // Get the response from the buffer
            CURL_easy_cleanup(hCurl)
            ? "response", cResponse
        ELSE
            cResponse := "Failed to initialize cURL session."
        ENDIF
    
        RETURN cResponse

I would be so happy if anyone could run the small sample and tell me if they experience the same? Or what to do about it...


Very kind regards and thank you in advance,
Ruth
Posts: 1344
Joined: Wed Nov 16, 2005 09:14 PM
Re: hb_base64encode() stays empty
Posted: Wed May 15, 2024 12:26 PM
Ruth:
Has esta prueba
Code (fw): Select all Collapse
// C:\FWH\SAMPLES\RUTHBASE64.PRG

#include "FiveWin.ch"
#Include "Outlook.ch"
#Include "Mail.ch"


FUNCTION Main()

  LOCAL cImgPath, cImgBase64 := {}, cImgMemo
 
  cImgPath     := "c:\fwh\samples\img\start_slide1.jpg"
  cImgMemo     := MEMOREAD(cImgPath)
  AAdd(cImgBase64  , hb_base64encode(MEMOREAD(cImgPath)))
 
? "cImgPath", cImgPath
? "cImgMemo", cImgMemo
xbrowse( cImgBase64 )

RETURN NIL
Luego exporta a Excel y veras el valor que te está dejando
Posts: 179
Joined: Fri Dec 07, 2007 01:26 PM
Re: hb_base64encode() stays empty
Posted: Wed May 15, 2024 05:21 PM

Dear Mr. Gomez, dear friends,

thank you a lot for helping me. I appreciate it very much.

Please can you help me understand further. I combined now that

modharbour returns a string for hb_base64encode()

whereas in xharbour it returns an array.

Is this a correct assumption? Thank you for your help.

Or is it that the returned value is too long for a string in xharbour....

Many, many thanks and kind regards

Ruth

Posts: 231
Joined: Fri Jul 20, 2012 01:49 AM
Re: hb_base64encode() stays empty
Posted: Wed May 15, 2024 06:38 PM
Hi Ruth,

for xHarbour you should send 2 parameters, the first one is the string and second one is the lenght.
Code (fw): Select all Collapse
cRaw := memoReady( "yourFile" )
cBase64 := hb_base64encode( cRaw, len( cRaw ) )
this way you will have a string as return.

Let me know if it worked.
Regards,

Lailton Fernando Mariano
Posts: 179
Joined: Fri Dec 07, 2007 01:26 PM
Re: hb_base64encode() stays empty
Posted: Wed May 15, 2024 07:49 PM
Dear Lailton,


this is so wonderful!!! Thank you very much :) Now with the 2 parameters in the function I get a value back also in xharbour.

But what happens now when I send an email with the base64-encoded content using cdo I suppose is that Microsoft adds unwanted characters and linebreaks and doesn´t embed the string seamlessly.



maybe it is better to stick with the inline attachements when wanting to send images over cdo ...


kind regards to you all and thanks again
Ruth
Posts: 231
Joined: Fri Jul 20, 2012 01:49 AM
Re: hb_base64encode() stays empty
Posted: Wed May 15, 2024 10:24 PM
Great!

%20 is related to some "space" in your string.

try to replace this line:
Code (fw): Select all Collapse
 + '<img src=\"data:image/jpeg;base64,' + cImgBase64 + '\" > ';
with
Code (fw): Select all Collapse
 + '<img src="data:image/jpeg;base64,'+alltrim(cImgBase64)+'">';
then try it again.
Regards,

Lailton Fernando Mariano
Posts: 179
Joined: Fri Dec 07, 2007 01:26 PM
Re: hb_base64encode() stays empty
Posted: Thu May 16, 2024 07:56 AM
Dear Lailton,

thank you very much for helping me. I tried with alltrim now - but it seems to make no difference. I think microsoft refuses the long string here maybe... :?:

If I put the code I post below it adds an unwanted
!
after about 2 1/2 lines of characters for the
Code (fw): Select all Collapse
   "<p>" + alltrim(cImgBase64) + "</p>"
and it even cuts off the string and adds some
!%
for this part of the code
Code (fw): Select all Collapse
   "<img src='data:image/jpeg;base64," + alltrim(cImgBase64) + "'>"
Now I have the suspicion that microsoft causes the issues here - however with microsoft.graph, mod_harbour, curl,... it is working perfectly.

I also think: is there an advantage integrating the images in the email base64encoded or is it evenly good to do it the "inline-attachement" way...

In the meantime, thank you, kind regards to all and have a nice day
Ruth




Code (fw): Select all Collapse
 :HTMLBody := "<h1>Hello!</h1><p>This is a test email with an inline image.</p>" + ;
                         "<img src='cid:id_image'>" + ;
                          "<p>Best Regards!</p>" + ;
                        "<p>" + alltrim(cImgBase64) + "</p>" + ;
                        "<hr>" +;
                        "<img src='data:image/jpeg;base64," + alltrim(cImgBase64) + "'>";
Posts: 1344
Joined: Wed Nov 16, 2005 09:14 PM
Re: hb_base64encode() stays empty
Posted: Thu May 16, 2024 12:52 PM
Ruth
Prueba con
Code (fw): Select all Collapse
cImgBase64 := STRTRAN(cImgBase64,CRLF,'')
Esto le quita todos los saltos de linea
Posts: 231
Joined: Fri Jul 20, 2012 01:49 AM
Re: hb_base64encode() stays empty
Posted: Thu May 16, 2024 11:16 PM
Like @cmsoft said, try something like:
Code (fw): Select all Collapse
cImgBase64 := strtran( strtran( cImgBase64 ), CRLF ), "=" )
I tested it with an old version xhb and worked

if it still not working for you, can you tell us which version xhb are you using?
Regards,

Lailton Fernando Mariano
Posts: 179
Joined: Fri Dec 07, 2007 01:26 PM
Re: hb_base64encode() stays empty
Posted: Fri May 17, 2024 09:09 AM
Dear friends,

thank you so much for your help.
Now I also added a MEMOWRIT() to see the return value of hb_base64encode() before anything is processed through microsoft cdo object.

I get perfectly fine base64 output. When I insert it to
https://base64.guru/converter/decode/image
it successfully displays my image.



This leads me to believe that the unwanted characters are added by the microsoft CDO.


Kind regards to you and many thanks again :-)
Ruth
Posts: 231
Joined: Fri Jul 20, 2012 01:49 AM
Re: hb_base64encode() stays empty
Posted: Fri May 17, 2024 04:46 PM
Excellent :)
Regards,

Lailton Fernando Mariano

Continue the discussion