Curl experts?

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Curl experts?

Post by Michael Vogel »

I've no idea if the following linux command could be converted to PureBasic commands. As I understood, the -H parameters are indicating special header information, so this is even more confusing me now...

Code: Select all

curl -H "Garmin-Client-Name: CoreService" -H "Content-Type: application/octet-stream" --data-binary @garmin-postdata http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData > EPO.BIN
Played around with libcurl with no success...
...so it would be already a valuable information for me, if anyone knows that this couldn't be done easily.

Code: Select all

curl = curl_easy_init()
url.s = str2curl("http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
agent.s = str2curl("pbcurl/1.0")
cookie.s = str2curl("")
post.s = str2curl("--data-binary")
header.s = str2curl("{"+#CR$+"'Garmin-Client-Name' => 'CoreService',"+#CR$+"'Content-Type' => 'application/octet-stream',"+#CR$+"'Content-Length' => '63'"+#CR$+"}")
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi Michael,

it's working a bit different.
Look here:
https://curl.haxx.se/libcurl/c/curl_slist_append.html

You can set own options with a list.

And don't use str2curl() anymore.
You run into problems, when the buffer is overwritten by the next call.

Better solution is to define

Code: Select all

curl_easy_setopt_str(handle.i, option.i, parameter.p-utf8) As "_curl_easy_setopt"
Explanation:
viewtopic.php?f=12&t=70245&hilit=libcurl+str2curl

This additional cur_easy_setopt_str() solves all problems. (buffer overwriting, threadsafe ...)

Bernd
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi,

maybe this works. Up to now I never uploaded a file.
If every thing fails you hafe to read in the file and 'post' the data somehow ...
Since I also not know a server where I can test it, I can not help you more.

Code: Select all

;curl -H "Garmin-Client-Name: CoreService" -H "Content-Type: application/octet-stream" --Data-binary @garmin-postdata http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData > EPO.BIN


IncludeFile "libcurl.pbi"



Define.i curl, hd_src
Define *headers.Curl_Slist


InitNetwork()

curl = curl_easy_init()
If curl
  
  curl_easy_setopt(curl, #CURLOPT_HEADER, 1)
  
  *headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService");
  *headers = curl_slist_append(*headers, "Content-Type: application/octet-stream");
  curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)   
  
  curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
  
  curl_easy_setopt(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")

  curl_easy_setopt(curl, #CURLOPT_UPLOAD, 1)
  
  curl_easy_setopt(curl, #CURLOPT_PUT, 1)
  
  curl_easy_setopt(curl, #CURLOPT_INFILESIZE_LARGE, FileSize("garmin-postdata"))
  
  hd_src = ReadFile(#PB_Any, "garmin-postdata")
  
  curl_easy_setopt(curl, #CURLOPT_READDATA, hd_src)
  
  
  curl_easy_setopt(curl,#CURLOPT_WRITEFUNCTION,@LibCurl_WriteFunction())
  
  If curl_easy_perform(curl) = #CURLE_OK
    
    Result$ =  LibCurl_GetData()
    Debug Result$
    
  EndIf
  
  CloseFile(hd_src)
  
  curl_slist_free_all(*headers)
  
  curl_easy_cleanup(curl)
EndIf
Btw.:

Code: Select all


Define LibCurl_ReceivedData$

ProcedureC.l LibCurl_WriteFunction(*ptr, Size, NMemB, Target.i)
  ;retreives utf-8/ascii encoded data
  Protected SizeProper.i  = Size & 255
  Protected NMemBProper.i = NMemB
  Protected *String.String
  Shared LibCurl_ReceivedData$
  
  If Target = #Null
    LibCurl_ReceivedData$ + PeekS(*ptr, SizeProper * NMemBProper, #PB_UTF8|#PB_ByteLength)
  Else
    If IsFile(Target)
      WriteData(Target, *ptr, SizeProper * NMemBProper)
    Else
      ;*String\s + PeekS(*ptr, SizeProper * NMemBProper, #PB_UTF8|#PB_ByteLength)
      LibCurl_ReceivedData$ + PeekS(*ptr, SizeProper * NMemBProper, #PB_UTF8|#PB_ByteLength)
    EndIf
  EndIf
  
  ProcedureReturn SizeProper * NMemBProper
  
EndProcedure




Procedure.s LibCurl_GetData()
  Shared LibCurl_ReceivedData$
  Protected ReturnData$
  
  ReturnData$ = LibCurl_ReceivedData$
  LibCurl_ReceivedData$ = ""
  
  ProcedureReturn ReturnData$
  
EndProcedure

User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Curl experts?

Post by Michael Vogel »

You did a good job - even when an error message is returned, it's much more I would have been able to do...
I don't have a working solution on my computer, then I would be able to capture the network traffic for further investigations. But there are many code snippets in the internet and all authors say their program works fine (on Linux, MAC, etc.)

Here are some of these code examples:

Code: Select all

// retrieveData makes a HTTP request to get Garmin EPO data and returns the body as []byte if successful.
func retrieveData() ([]byte, error) {
	url := "https://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData"
	// Data from https://www.kluenter.de/garmin-ephemeris-files-and-linux/
	data := []byte("\n-\n\aexpress\u0012\u0005de_DE\u001A\aWindows\"" +
		"\u0012601 Service Pack 1\u0012\n\b\x8C\xB4\x93\xB8" +
		"\u000E\u0012\u0000\u0018\u0000\u0018\u001C\"\u0000")

	resp, err := http.Post(url, "application/octet-stream", bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil
}

Code: Select all

<?php
if (file_exists ('EPO.BIN')) {
	if (filemtime ('EPO.BIN') > time() - 6 * 3600) {
		header ('Expires: -1');
		header ('Content-Type: application/save');
		header ('Content-Length: ' . filesize ('EPO.BIN'));
		header ('Content-Disposition: attachment; filename="EPO.BIN"');
		ob_clean();
		flush();
		readfile ('EPO.BIN');
		exit;
	}
}
$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt ($ch, CURLOPT_URL, 'http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData');
curl_setopt ($ch, CURLOPT_HTTPHEADER, array ('Garmin-Client-Name: CoreService', 'Content-Type: application/octet-stream', 'Content-length: 63'));
curl_setopt ($ch, CURLOPT_POST, TRUE);
curl_setopt ($ch, CURLOPT_BINARYTRANSFER, TRUE);
$fh = fopen ('garmin-postdata','r');
curl_setopt ($ch, CURLOPT_INFILE, $fh);
$result = curl_exec($ch);
curl_close ($ch);
fclose ($fh);
header ('Expires: -1');
header ('Content-Type: application/save');
header ('Content-Length: ' . (strlen ($result) * 2304 / 2307));
header ('Content-Disposition: attachment; filename="EPO.BIN"');
$data = str_split ($result, 2307);
$output = '';
for ($i = 0; $i < count ($data); $i++) {
	$output .= substr ($data[$i], 3);
}
$fh = fopen ('EPO.BIN','wb');
fwrite ($fh, $output);
fclose ($fh);
ob_clean();
flush();
echo $output;
?>

Code: Select all

echo "Fetching Garmin satellite data."
curl --silent \
--header "Garmin-Client-Name: CoreService" \
--header "Content-Type: application/octet-stream" \
--data-binary "@${BASEDIR}/garmin-postdata" \
http://omt.garmin.com/Rce/ProtobufAp...tEphemerisData \
> "$tmpepo"
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Your second example shows that it is a post request, not a put.
I changed the code.

Code: Select all

IncludeFile "libcurl.pbi"



Define.i curl, hd_src
Define *headers.Curl_Slist


InitNetwork()

curl = curl_easy_init()
If curl
 
  curl_easy_setopt(curl, #CURLOPT_HEADER, 1)
 
  *headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService");
  *headers = curl_slist_append(*headers, "Content-Type: application/octet-stream");
  curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)   
 
  curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
 
  curl_easy_setopt(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")

  curl_easy_setopt(curl, #CURLOPT_UPLOAD, 1)
 
  curl_easy_setopt(curl, #CURLOPT_POST, 1)
  curl_easy_setopt(curl, #CURLOPT_BINARYTRANSFER, 1)
 
  curl_easy_setopt(curl, #CURLOPT_INFILESIZE_LARGE, FileSize("garmin-postdata"))
 
  hd_src = ReadFile(#PB_Any, "garmin-postdata")
 
  curl_easy_setopt(curl, #CURLOPT_READDATA, hd_src)
 
 
  curl_easy_setopt(curl,#CURLOPT_WRITEFUNCTION,@LibCurl_WriteFunction())
 
  If curl_easy_perform(curl) = #CURLE_OK
   
    Result$ =  LibCurl_GetData()
    Debug Result$
   
  EndIf
 
  CloseFile(hd_src)
 
  curl_slist_free_all(*headers)
 
  curl_easy_cleanup(curl)
EndIf
You should check with wireshark if the file content is inside the packets.
Becuase I don't know if curl can handle the PB file in the correct way.

Bernd
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi Michael,

tested as far as I could:

Code: Select all

IncludeFile "libcurl.pbi"



Define.i curl, hd_src
Define *headers.Curl_Slist


InitNetwork()

File = ReadFile(#PB_Any, "garmin-postdata")
If File
  *Buffer = AllocateMemory(Lof(File))
  If *Buffer
    
    If ReadData(File, *Buffer, MemorySize(*Buffer)) = MemorySize(*Buffer)
      
      curl = curl_easy_init()
      If curl
        
        curl_easy_setopt(curl, #CURLOPT_HEADER, 1)
        
        *headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService")
        *headers = curl_slist_append(*headers, "Content-Type: application/octet-stream")
        curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)
        
        curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
        curl_easy_setopt_str(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")
        curl_easy_setopt(curl, #CURLOPT_POST, 1)
        
        curl_easy_setopt(curl, #CURLOPT_POSTFIELDSIZE, MemorySize(*Buffer))
        
        curl_easy_setopt(curl, #CURLOPT_POSTFIELDS, *Buffer)
        
        curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())
        
        If curl_easy_perform(curl) = #CURLE_OK
          
          Result$ =  LibCurl_GetData()
          Debug Result$
          
        EndIf
        
        curl_slist_free_all(*headers)
        
        curl_easy_cleanup(curl)
      EndIf
      
    EndIf
    
    FreeMemory(*Buffer)
    
  EndIf
  CloseFile(File)
EndIf
I tested it with wireshark: the file is included as post data.

Bernd
Last edited by infratec on Mon Aug 20, 2018 7:18 am, edited 1 time in total.
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Curl experts?

Post by Michael Vogel »

Bernd, thanks for all your efforts - could you also tell me if you have a modified libcurl.pbi?

This one is definitely a little bit different, to add "curl_easy_setopt_str" was not that difficult (because of your hints), but there is much more missing, like the constants #CURLOPT_BINARYTRANSFER and I don't know how the LibCurl_ReadCallback should look like...
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi Michael,

CURLOPT_BINARYTRANSFER
was a mistake, because it is not used by curl_easy_....

It is not used in my last code.
I also removed the Read function, because with providing the *Buffer by self, this is also not needed.

Btw. my current version of LibCurl.pbi is here:

https://oc.ednt.de/index.php/s/UeeKoMco3is23Zk

Bernd
User avatar
Michael Vogel
Addict
Addict
Posts: 2677
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Curl experts?

Post by Michael Vogel »

Bernd, thanks once more again :wink:

Converted the postdata as found in a snippet (see above) and there's data which is returned - hurray!

Code: Select all

DisableExplicit

DataSection
	GarminPostdata:
	Data.q $72707865070A2D0A,$5F65640512737365,$646E6957071A4544,$313036122273776F,$6563697672655320,$1231206B63615020,$120EB893B48C080A,$221C18001800
EndDataSection

*Buffer=?GarminPostdata
#BufferSize=63

Define.i curl, hd_src
Define *headers.Curl_Slist

InitNetwork()

; File = ReadFile(#PB_Any, "garmin-postdata")
; If File
;	*Buffer = AllocateMemory(Lof(File))
;	If *Buffer
;		If ReadData(File, *Buffer, MemorySize(*Buffer)) = MemorySize(*Buffer)

curl = curl_easy_init()
If curl

	curl_easy_setopt(curl, #CURLOPT_HEADER, 1)

	*headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService")
	*headers = curl_slist_append(*headers, "Content-Type: application/octet-stream")
	curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)

	curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
	curl_easy_setopt_str(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")
	curl_easy_setopt(curl, #CURLOPT_POST, 1)
	curl_easy_setopt(curl, #CURLOPT_POSTFIELDSIZE, #BufferSize); MemorySize(*Buffer))
	curl_easy_setopt(curl, #CURLOPT_POSTFIELDS, *Buffer)

	curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())

	If curl_easy_perform(curl) = #CURLE_OK
		Result$ =  LibCurl_GetData()
		Debug Result$
		Debug Len(result$)
		handle=CreateFile(#PB_Any,"Epo.bin")
		If handle
			WriteString(handle,result$)
			CloseFile(handle)
		EndIf
	EndIf

	curl_slist_free_all(*headers)

	curl_easy_cleanup(curl)
EndIf

; 		EndIf
;		FreeMemory(*Buffer)
;	EndIf
;	CloseFile(File)
; EndIf

Anyhow it's completely different to the expected data (Extended Prediction Orbit for GPS satellites), below are the first bytes of such an EPO binary:

Code: Select all

DataSection
Data.b 88,42,5,1,37,2,100,219,29,222,14,7,159,12,167,252
Data.b 72,51,28,251,29,222,14,7,194,58,55,7,49,80,179,133
Data.b 128,136,241,7,34,152,19,236,147,178,47,3,157,120,3,166
Data.b 125,207,213,85,103,210,149,32,248,81,198,27,28,0,0,16
Data.b 0,0,0,0,11,235,22,111,88,42,5,2,209,2,100,157
Data.b 91,238,14,7,191,35,235,253,34,0,38,252,11,239,14,7
Data.b 187,11,58,248,180,216,142,152,133,180,241,7,138,128,179,240
Data.b 42,76,57,14,29,117,0,166,181,15,66,87,111,127,207,33
Data.b 244,226,27,181,28,0,0,16,0,0,0,148,65,70,245,230
Data.b 88,42,5,3,235,2,100,51,245,1,14,7,255,53,218,249
Data.b 181,14,5,248,220,1,14,7,79,31,0,7,214,12,138,153
Data.b 74,166,241,7,49,211,186,197,28,109,214,7,79,136,3,166
Data.b 77,86,89,122,174,227,33,32,191,233,56,23,28,0,0,16
Data.b 0,0,144,50,33,204,122,163,88,42,5,0,0,0,100,0
Data.b 198,49,14,7,198,49,14,7,198,49,14,7,198,49,14,7
Data.b 198,49,14,7,198,49,206,56,198,49,14,7,198,49,14,7
Data.b 198,49,14,7,198,49,14,7,198,49,14,7,198,49,14,7
Data.b 0,0,0,0,28,0,0,80,0,0,239,239,68,42,78,128
Data.b 88,42,5,5,39,3,100,4,194,97,14,7,21,87,173,249
Data.b 64,111,196,250,128,97,14,7,7,124,223,248,90,135,49,133
Data.b 220,199,241,7,113,175,7,99,73,31,212,5,164,125,0,166
Data.b 201,187,105,123,116,116,169,33,188,211,222,26,28,0,0,16
Data.b 0,0,0,0,104,252,218,232,88,42,5,6,57,3,100,217
Data.b 31,174,14,7,162,125,115,252,90,64,117,251,237,81,14,7
Data.b 1,74,202,248,89,23,130,132,239,251,241,7,54,61,72,243
Data.b 59,181,143,7,26,44,3,166,101,72,139,85,55,150,150,32
Data.b 36,185,231,211,28,0,0,16,0,0,16,1,161,142,240,70
Data.b 88,42,5,7,148,61,100,199,1,190,14,7,87,114,124,0
Data.b 229,80,7,0,61,190,14,7,192,90,83,7,252,208,74,132
Data.b 91,228,241,7,109,97,128,215,122,182,38,1,129,112,3,166
Data.b 195,180,86,212,181,121,10,32,122,139,35,154,28,0,0,16
Data.b 0,0,16,0,163,186,56,74,88,42,5,8,149,62,100,245
Data.b 51,78,14,7,181,159,70,254,219,189,66,253,206,177,14,7
Data.b 240,147,62,7,77,226,114,137,191,22,241,7,226,212,131,85
Data.b 106,207,200,6,89,91,2,166,206,94,126,32,58,159,142,32
Data.b 203,75,178,239,28,0,0,16,0,0,0,34,174,100,211,95
Data.b 88,42,5,9,60,62,100,244,50,94,14,7,7,151,208,249
Data.b 43,177,55,248,197,161,14,7,80,186,2,7,86,27,222,133
Data.b 110,7,241,7,177,82,79,85,229,212,116,7,101,219,2,166
Data.b 254,27,97,160,76,191,193,33,120,77,128,72,28,0,0,16
Data.b 0,0,16,1,48,223,162,85,88,42,5,10,202,2,100,244
Data.b 50,110,14,7,90,162,109,249,221,158,160,249,250,145,14,7
Data.b 127,140,244,248,180,139,72,130,83,54,241,7,19,245,44,158
Data.b 46,34,235,6,242,216,3,166,45,71,61,122,166,61,62,32
Data.b 3,63,155,142,28,0,0,16,0,0,0,2,30,144,189,123
Data.b 88,42,5,11,186,0,100,20,210,129,14,7,182,191,189,255
Data.b 55,145,84,254,95,126,14,7,192,152,107,248,140,198,102,139
Data.b 248,31,241,7,253,166,162,215,240,44,183,15,152,185,3,166
Data.b 4,63,53,70,113,178,229,35,76,109,92,73,28,0,0,16
Data.b 0,0,0,1,234,105,238,41,88,42,5,0,0,0,100,0
Data.b 198,49,14,7,198,49,14,7,198,49,14,7,198,49,14,7
Data.b 198,49,14,7,198,49,142,7,198,49,14,7,198,49,14,7
Data.b 198,49,14,7,198,49,14,7,198,49,14,7,198,49,14,7
Data.b 0,0,0,0,28,0,0,80,0,0,0,0,68,42,225,80
Data.b 88,42,5,13,81,62,100,6,192,225,14,7,172,208,221,7
Data.b 110,243,185,7,193,225,14,7,117,251,210,248,112,231,51,132
Data.b 35,72,241,7,184,188,167,22,155,118,188,6,237,178,3,166
Data.b 214,15,212,171,147,95,127,32,204,46,212,60,28,0,0,16
Data.b 0,0,0,0,183,101,114,97,88,42,5,14,22,61,100,1
Data.b 199,209,14,7,50,227,151,7,207,195,80,7,151,209,14,7
Data.b 140,203,104,248,154,28,178,131,43,120,241,7,168,39,110,63
Data.b 190,114,38,2,223,62,2,166,123,3,17,172,30,134,42,32
Data.b 72,88,220,176,28,0,0,16,0,0,0,1,38,46,32,197
Data.b 88,42,5,15,229,62,100,8,206,193,14,7,44,250,244,249
Data.b 151,208,254,249,191,62,14,7,113,216,116,248,145,86,58,134
Data.b 200,100,241,7,160,117,99,24,116,196,108,2,244,163,0,166
Data.b 182,9,121,163,204,169,222,34,238,149,97,28,28,0,0,16
Data.b 0,0,0,0,247,12,29,79,88,42,5,16,20,0,100,241
Data.b 55,206,15,7,207,29,75,3,111,56,203,4,198,49,15,7
Data.b 217,23,184,248,41,93,207,134,181,152,240,7,73,44,199,108
Data.b 165,13,19,2,70,66,2,166,20,90,190,7,201,187,62,47
Data.b 237,248,77,21,28,0,0,16,0,0,0,0,222,88,125,122
Data.b 88,42,5,17,115,63,100,37,227,33,15,7,76,8,213,255
Data.b 121,45,42,253,236,33,15,7,208,3,216,248,143,249,242,154
Data.b 20,141,240,7,119,36,105,68,91,10,109,1,90,241,3,166
Data.b 218,202,7,45,247,1,2,47,142,77,152,183,28,0,0,16
Data.b 0,0,16,18,147,30,206,7,88,42,5,18,52,2,100,38
Data.b 224,17,15,7,59,35,193,253,204,2,56,252,177,238,15,7
Data.b 133,8,12,7,193,157,14,153,94,181,240,7,30,72,159,230
:
:

EndDataSection
Some background information - some GPS devices using prediction information to get a (much) quicker location fix. Garmin's sport watches need additional tools and this is not very comfortable...
...I wrote a windows tool which recognizes when a watch has been connected to the USB port (for charching the battery) and makes not only a backup of all new activities automatically but also updates the watch with this EPO data.

Bad luck, the source of the EPO data allows this for single user (like me), but not in a program for the public. So I am searching for alternatives which would allow everyone to use this nice feature...
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi Michael,

an 'optimized' version:

Code: Select all

EnableExplicit

IncludeFile "LibCurl.pbi"


Define.i curl, hd_src, outfile
Define *headers.Curl_Slist, *Buffer


DataSection
  GarminPostdata:
  Data.q $72707865070A2D0A,$5F65640512737365,$646E6957071A4544,$313036122273776F,$6563697672655320,$1231206B63615020,$120EB893B48C080A,$221C18001800
EndDataSection

*Buffer=?GarminPostdata
#BufferSize=63



InitNetwork()

curl = curl_easy_init()
If curl
  
  curl_easy_setopt(curl, #CURLOPT_HEADER, 0)
  
  *headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService")
  *headers = curl_slist_append(*headers, "Content-Type: application/octet-stream")
  curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)
  
  curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
  curl_easy_setopt_str(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")
  curl_easy_setopt(curl, #CURLOPT_POST, 1)
  curl_easy_setopt(curl, #CURLOPT_POSTFIELDSIZE, #BufferSize); MemorySize(*Buffer))
  curl_easy_setopt(curl, #CURLOPT_POSTFIELDS, *Buffer)
  
  
  outfile = OpenFile(#PB_Any, "Epo.bin")
  
  curl_easy_setopt(curl, #CURLOPT_WRITEDATA, outfile)
  
  curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())
  
  If curl_easy_perform(curl) = #CURLE_OK
    Debug "Ok"
  EndIf
  
  CloseFile(outfile)
  
  curl_slist_free_all(*headers)
  
  curl_easy_cleanup(curl)
EndIf
If you save binatry data, it's better to store them directly and without the header.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

According to:

https://github.com/StevenMaude/armstron ... mstrong.go

You can check the filesize: 28*2307 = 64596
But then you have to remove the first 3 bytes from each EPO record.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hi Michael,

I updated LibCurl.pbi to allow binary result in a memorybuffer.
Simply download it again.

Then use:

Code: Select all

EnableExplicit

IncludeFile "LibCurl.pbi"


Define.i curl, hd_src, outfile, i
Define *headers.Curl_Slist, *Res



DataSection
  GarminPostdataStart:
  Data.a #LF, '-', #LF
  Data.a 7, 'e', 'x', 'p', 'r', 'e', 's', 's'
  Data.a #DC2
  Data.a 5, 'd', 'e', '_', 'D', 'E'
  Data.a #SUB
  Data.a 7, 'W', 'i', 'n', 'd', 'o', 'w', 's'
  Data.a '"'
  Data.a 18, '6', '0', '1', ' ', 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'a', 'c', 'k', ' ', '1'
  Data.a #DC2
  Data.a #LF, $08, $8C, $B4, $93, $B8, $0E, $12
  Data.a $00, $18, $00, $18, $1C, $22, $00
  GarminPostdataEnd:
EndDataSection



InitNetwork()

curl = curl_easy_init()
If curl
  
  curl_easy_setopt(curl, #CURLOPT_HEADER, 0)
  
  *headers = curl_slist_append(*headers, "Garmin-Client-Name: CoreService")
  *headers = curl_slist_append(*headers, "Content-Type: application/octet-stream")
  curl_easy_setopt(curl, #CURLOPT_HTTPHEADER, *headers)
  
  curl_easy_setopt_str(curl,#CURLOPT_URL, "http://omt.garmin.com/Rce/ProtobufApi/EphemerisService/GetEphemerisData")
  curl_easy_setopt_str(curl,#CURLOPT_USERAGENT, "pbcurl/1.0")
  curl_easy_setopt(curl, #CURLOPT_POST, 1)
  curl_easy_setopt(curl, #CURLOPT_POSTFIELDSIZE, ?GarminPostdataEnd - ?GarminPostdataStart)
  curl_easy_setopt(curl, #CURLOPT_POSTFIELDS, ?GarminPostdataStart)
  
  
  ;outfile = CreateFile(#PB_Any, "Epo.bin")
  ;curl_easy_setopt(curl, #CURLOPT_WRITEDATA, outfile)
  
  curl_easy_setopt(curl, #CURLOPT_WRITEDATA, #Null) ; write data to memorybuffer *LibCurl_Buffer
  
  curl_easy_setopt(curl, #CURLOPT_WRITEFUNCTION, @LibCurl_WriteFunction())
  
  If curl_easy_perform(curl) = #CURLE_OK
    
    ;ShowMemoryViewer(*LibCurl_Buffer, MemorySize(*LibCurl_Buffer))
    
    If MemorySize(*LibCurl_Buffer) = 28 * 2307
      
      outfile = CreateFile(#PB_Any, "Epo.bin")
      If outfile
        
        *Res = *LibCurl_Buffer
        
        For i = 0 To 27
          WriteData(outfile, *Res + 3, 2304)
          *Res + 2307
        Next i
        
        CloseFile(outfile)
      EndIf
      
    EndIf
    
    FreeMemory(*LibCurl_Buffer)
    *LibCurl_Buffer = #Null
  EndIf
  
  ;CloseFile(outfile)
  
  curl_slist_free_all(*headers)
  
  curl_easy_cleanup(curl)
EndIf
Now you should have the right data.
(05 01 is at the right place comparde to your example data)
Last edited by infratec on Mon Aug 20, 2018 2:15 pm, edited 2 times in total.
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

If I compare my file with the file from:

http://www.javawa.nl/epo_en.html

I get no difference :wink:
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

Hm...

but you don't need curl for this :wink:
infratec
Always Here
Always Here
Posts: 6874
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Curl experts?

Post by infratec »

So my help was not needed: :mrgreen:

Code: Select all


DataSection
  GarminPostdataStart:
  Data.a #LF, '-', #LF
  Data.a 7, 'e', 'x', 'p', 'r', 'e', 's', 's'
  Data.a #DC2
  Data.a 5, 'd', 'e', '_', 'D', 'E'
  Data.a #SUB
  Data.a 7, 'W', 'i', 'n', 'd', 'o', 'w', 's'
  Data.a '"'
  Data.a 18, '6', '0', '1', ' ', 'S', 'e', 'r', 'v', 'i', 'c', 'e', ' ', 'P', 'a', 'c', 'k', ' ', '1'
  Data.a #DC2
  Data.a #LF, $08, $8C, $B4, $93, $B8, $0E, $12
  Data.a $00, $18, $00, $18, $1C, $22, $00
  GarminPostdataEnd:
EndDataSection


InitNetwork()


Header$ = "POST /Rce/ProtobufApi/EphemerisService/GetEphemerisData HTTP/1.1" + #CRLF$
Header$ + "Host: omt.garmin.com" + #CRLF$
Header$ + "User-Agent: pbcurl/1.0" + #CRLF$
Header$ + "Garmin-Client-Name: CoreService" + #CRLF$
Header$ + "Content-Type: application/octet-stream" + #CRLF$
Header$ + "Content-Length: " + Str(?GarminPostdataEnd - ?GarminPostdataStart) + #CRLF$
Header$ + #CRLF$

*Buffer = AllocateMemory(4096)
If *Buffer
  
  Con = OpenNetworkConnection("omt.garmin.com", 80)
  If Con
    
    If SendNetworkString(Con, Header$)
      If SendNetworkData(Con, ?GarminPostdataStart, ?GarminPostdataEnd - ?GarminPostdataStart)
        Timeout = 100
        
        Repeat
          
          Select NetworkClientEvent(Con)
            Case #PB_NetworkEvent_None
              Delay(10)
              Timeout - 1
              
            Case #PB_NetworkEvent_Disconnect
              Timeout = 0
              
            Case #PB_NetworkEvent_Data
              RcvLen = ReceiveNetworkData(Con, *Buffer + Index, MemorySize(*Buffer))
              If Not HeaderEndPos
                If FindString(PeekS(*Buffer, 20, #PB_UTF8), "200 OK")
                  HeaderEndPos = FindString(PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8), #CRLF$ + #CRLF$)
                  If HeaderEndPos
                    HeaderEndPos + 3
                    Pos = FindString(PeekS(*Buffer, MemorySize(*Buffer), #PB_UTF8), "Content-Length:")
                    If Pos
                      Pos + 15
                      ContentLength = Val(PeekS(*Buffer + Pos, 10, #PB_UTF8))
                      *Buffer = ReAllocateMemory(*Buffer, HeaderEndPos + ContentLength)
                    Else
                      Timeout = 0
                    EndIf
                  EndIf
                Else
                  Timeout = 0
                EndIf                
              EndIf
              Index + RcvLen
              Debug index
              If Index = MemorySize(*Buffer) + 1
                Break
              EndIf
              
          EndSelect
          
        Until Timeout = 0
        
        If Not Timeout
          ShowMemoryViewer(*Buffer + HeaderEndPos, MemorySize(*Buffer) - HeaderEndPos)
          
          If MemorySize(*Buffer) - HeaderEndPos = 28 * 2307
            
            outfile = CreateFile(#PB_Any, "Epo.bin")
            If outfile
              
              *Res = *Buffer + HeaderEndPos
              
              For i = 0 To 27
                WriteData(outfile, *Res + 3, 2304)
                *Res + 2307
              Next i
              
              CloseFile(outfile)
            EndIf
            
          EndIf
          
        EndIf
        
      EndIf
    EndIf
    
    CloseNetworkConnection(Con)
  EndIf
  FreeMemory(*Buffer)
EndIf
Last edited by infratec on Mon Aug 20, 2018 3:56 pm, edited 1 time in total.
Post Reply