add many source files
This commit is contained in:
228
par/par_easycurl.h
Normal file
228
par/par_easycurl.h
Normal file
@@ -0,0 +1,228 @@
|
||||
// EASYCURL :: https://github.com/prideout/par
|
||||
// Wrapper around libcurl for performing simple synchronous HTTP requests.
|
||||
//
|
||||
// Distributed under the MIT License, see bottom of file.
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// BEGIN PUBLIC API
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PAR_EASYCURL_H
|
||||
#define PAR_EASYCURL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char par_byte;
|
||||
|
||||
// Call this before calling any other easycurl function. The flags are
|
||||
// currently unused, so you can just pass 0.
|
||||
void par_easycurl_init(unsigned int flags);
|
||||
|
||||
// Allocates a memory buffer and downloads a data blob into it.
|
||||
// Returns 1 for success and 0 otherwise. The byte count should be
|
||||
// pre-allocated. The caller is responsible for freeing the returned data.
|
||||
// This does not do any caching!
|
||||
int par_easycurl_to_memory(char const* url, par_byte** data, int* nbytes);
|
||||
|
||||
// Downloads a file from the given URL and saves it to disk. Returns 1 for
|
||||
// success and 0 otherwise.
|
||||
int par_easycurl_to_file(char const* srcurl, char const* dstpath);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// END PUBLIC API
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef PAR_EASYCURL_IMPLEMENTATION
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strncasecmp _strnicmp
|
||||
#define strcasecmp _stricmp
|
||||
#else
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
static int _ready = 0;
|
||||
|
||||
void par_easycurl_init(unsigned int flags)
|
||||
{
|
||||
if (!_ready) {
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
_ready = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void par_easycurl_shutdown()
|
||||
{
|
||||
if (_ready) {
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
static size_t onheader(void* v, size_t size, size_t nmemb)
|
||||
{
|
||||
size_t n = size * nmemb;
|
||||
char* h = (char*) v;
|
||||
if (n > 14 && !strncasecmp("Last-Modified:", h, 14)) {
|
||||
char const* s = h + 14;
|
||||
time_t r = curl_getdate(s, 0);
|
||||
if (r != -1) {
|
||||
// TODO handle last-modified
|
||||
}
|
||||
} else if (n > 5 && !strncasecmp("ETag:", h, 5)) {
|
||||
// TODO handle etag
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
par_byte* data;
|
||||
int nbytes;
|
||||
} par_easycurl_buffer;
|
||||
|
||||
static size_t onwrite(char* contents, size_t size, size_t nmemb, void* udata)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
par_easycurl_buffer* mem = (par_easycurl_buffer*) udata;
|
||||
mem->data = (par_byte*) realloc(mem->data, mem->nbytes + realsize + 1);
|
||||
if (!mem->data) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(mem->data + mem->nbytes, contents, realsize);
|
||||
mem->nbytes += realsize;
|
||||
mem->data[mem->nbytes] = 0;
|
||||
return realsize;
|
||||
}
|
||||
|
||||
#if IOS_EXAMPLE
|
||||
bool curlToMemory(char const* url, uint8_t** data, int* nbytes)
|
||||
{
|
||||
NSString* nsurl =
|
||||
[NSString stringWithCString:url encoding:NSASCIIStringEncoding];
|
||||
NSMutableURLRequest* request =
|
||||
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:nsurl]];
|
||||
[request setTimeoutInterval: TIMEOUT_SECONDS];
|
||||
NSURLResponse* response = nil;
|
||||
NSError* error = nil;
|
||||
// Use the simple non-async API because we're in a secondary thread anyway.
|
||||
NSData* nsdata = [NSURLConnection sendSynchronousRequest:request
|
||||
returningResponse:&response
|
||||
error:&error];
|
||||
if (error == nil) {
|
||||
*nbytes = (int) [nsdata length];
|
||||
*data = (uint8_t*) malloc([nsdata length]);
|
||||
memcpy(*data, [nsdata bytes], [nsdata length]);
|
||||
return true;
|
||||
}
|
||||
BLAZE_ERROR("%s\n", [[error localizedDescription] UTF8String]);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int par_easycurl_to_memory(char const* url, par_byte** data, int* nbytes)
|
||||
{
|
||||
char errbuf[CURL_ERROR_SIZE] = {0};
|
||||
par_easycurl_buffer buffer = {(par_byte*) malloc(1), 0};
|
||||
long code = 0;
|
||||
long status = 0;
|
||||
CURL* handle = curl_easy_init();
|
||||
curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_ENCODING, "gzip, deflate");
|
||||
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_MAXREDIRS, 8);
|
||||
curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, onwrite);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &buffer);
|
||||
curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, onheader);
|
||||
curl_easy_setopt(handle, CURLOPT_URL, url);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMEVALUE, 0);
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, 0);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMEOUT, 60);
|
||||
curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf);
|
||||
curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
CURLcode res = curl_easy_perform(handle);
|
||||
if (res != CURLE_OK) {
|
||||
printf("CURL Error: %s\n", errbuf);
|
||||
return 0;
|
||||
}
|
||||
curl_easy_getinfo(handle, CURLINFO_CONDITION_UNMET, &code);
|
||||
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &status);
|
||||
if (status == 304 || status >= 400) {
|
||||
return 0;
|
||||
}
|
||||
*data = buffer.data;
|
||||
*nbytes = buffer.nbytes;
|
||||
curl_easy_cleanup(handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int par_easycurl_to_file(char const* srcurl, char const* dstpath)
|
||||
{
|
||||
long code = 0;
|
||||
long status = 0;
|
||||
FILE* filehandle = fopen(dstpath, "wb");
|
||||
if (!filehandle) {
|
||||
printf("Unable to open %s for writing.\n", dstpath);
|
||||
return 0;
|
||||
}
|
||||
CURL* handle = curl_easy_init();
|
||||
curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_ENCODING, "gzip, deflate");
|
||||
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_MAXREDIRS, 8);
|
||||
curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
|
||||
curl_easy_setopt(handle, CURLOPT_WRITEDATA, filehandle);
|
||||
curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, onheader);
|
||||
curl_easy_setopt(handle, CURLOPT_URL, srcurl);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMEVALUE, 0);
|
||||
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, 0);
|
||||
curl_easy_setopt(handle, CURLOPT_TIMEOUT, 60);
|
||||
curl_easy_perform(handle);
|
||||
curl_easy_getinfo(handle, CURLINFO_CONDITION_UNMET, &code);
|
||||
curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &status);
|
||||
fclose(filehandle);
|
||||
if (status == 304 || status >= 400) {
|
||||
remove(dstpath);
|
||||
return 0;
|
||||
}
|
||||
curl_easy_cleanup(handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // PAR_EASYCURL_IMPLEMENTATION
|
||||
#endif // PAR_EASYCURL_H
|
||||
|
||||
// par_easycurl is distributed under the MIT license:
|
||||
//
|
||||
// Copyright (c) 2019 Philip Rideout
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
Reference in New Issue
Block a user