diff options
-rw-r--r-- | anteraja.c | 86 | ||||
-rw-r--r-- | common.h | 102 | ||||
-rw-r--r-- | pikul.c | 185 | ||||
-rw-r--r-- | private.h | 17 | ||||
-rw-r--r-- | sicepat.c | 61 |
5 files changed, 217 insertions, 234 deletions
@@ -1,4 +1,6 @@ -#include "common.h" +#include <stdlib.h> +#include <string.h> +#include "private.h" #define SERVICES_PATH "serviceRates" #define SERVICES_POST \ @@ -50,56 +52,55 @@ #define ORDER_ITEM_PRICE 9 #define ORDER_ITEM_WEIGHT 5 -static const char *status_trail[] = { "status", NULL }; static char *prefix = NULL; -void anteraja_init(char *provisions[]) +const char **anteraja_init(char *provisions[]) { - enum { BASE_PATH, ACCESS_KEY_ID, SECRET_ACCESS_KEY, PREFIX }; + enum { ACCESS_KEY_ID, SECRET_ACCESS_KEY, BASE_PATH, PREFIX }; shipping.base = malloc(strlen(provisions[BASE_PATH]) + 1); strcpy(shipping.base, provisions[BASE_PATH]); - headers((const char *[]){ "access-key-id", "secret-access-key", NULL }, &provisions[ACCESS_KEY_ID]); - shipping.headers = curl_slist_append(shipping.headers, "Content-Type:application/json"); if (provisions[PREFIX]) { prefix = malloc(strlen(provisions[PREFIX]) + 1); strcpy(prefix, provisions[PREFIX]); } + shipping.headers = curl_slist_append(shipping.headers, "Content-Type:application/json"); + static const char *status_trail[] = { "status", NULL }; + shipping.status_trail = status_trail; + static const char *fields[] = { "access-key-id", "secret-access-key", NULL }; + return fields; } -void anteraja_services(const char *origin, const char *destination, double weight, char **url, char **post) -{ - *url = malloc(strlen(shipping.base) + strlen(SERVICES_PATH) + 1); - sprintf(*url, "%s%s", shipping.base, SERVICES_PATH); - *post = malloc(strlen(SERVICES_POST) + strlen(origin) + strlen(destination) + SERVICES_WEIGHT - - 2 * strlen("%s") - strlen("%d") + 1); - sprintf(*post, SERVICES_POST, origin, destination, weight < 1.0 ? 1000 : (int)weight * 1000); -} - -size_t anteraja_services_handle(const char *contents, size_t size, size_t nmemb, - struct pikul_services **services) +const char **anteraja_services(const char *origin, const char *destination, double weight) { - size_t realsize = size * nmemb; - handle(SERVICES, contents, realsize, status_trail, (const char *[]){ - "content", - "services", - NULL - }, (const char *[]){ - "product_code", - "product_name", - "etd", - "rates" - }, services); - return realsize; + shipping.url = malloc(strlen(shipping.base) + strlen(SERVICES_PATH) + 1); + sprintf(shipping.url, "%s%s", shipping.base, SERVICES_PATH); + shipping.post = malloc(strlen(SERVICES_POST) + strlen(origin) + strlen(destination) + + SERVICES_WEIGHT - 2 * strlen("%s") - strlen("%d") + 1); + sprintf(shipping.post, SERVICES_POST, origin, destination, + weight < 1.0 ? 1000 : (int)weight * 1000); + static const char *trail[] = { + "content", + "services", + NULL + }; + shipping.trail = trail; + static const char *attributes[] = { + "product_code", + "product_name", + "etd", + "rates" + }; + return attributes; } void anteraja_order(const char *order_number, const char *service, const char *sender_name, const char *sender_phone, const char *origin, const char *sender_address, const char *sender_postal, const char *receiver_name, const char *receiver_phone, const char *destination, const char *receiver_address, const char *receiver_postal, - int nitems, char **items[], double subtotal, char **url, char **post) + int nitems, char **items[], double subtotal) { - *url = malloc(strlen(shipping.base) + strlen(ORDER_PATH) + 1); - sprintf(*url, "%s%s", shipping.base, ORDER_PATH); + shipping.url = malloc(strlen(shipping.base) + strlen(ORDER_PATH) + 1); + sprintf(shipping.url, "%s%s", shipping.base, ORDER_PATH); enum { SKU, QUANTITY, DESCRIPTION, PRICE, WEIGHT }; char *json = NULL; double total_weight = .0; @@ -131,27 +132,22 @@ void anteraja_order(const char *order_number, const char *service, const char *s else json[strlen(json)] = '\0'; } - *post = malloc(strlen(ORDER_POST) + strlen(prefix) + strlen(order_number) + strlen(service) + shipping.post = malloc(strlen(ORDER_POST) + strlen(prefix) + strlen(order_number) + strlen(service) + ORDER_WEIGHT + strlen(sender_name) + strlen(sender_phone) + strlen(origin) + strlen(sender_address) + strlen(sender_postal) + strlen(receiver_name) + strlen(receiver_phone) + strlen(destination) + strlen(receiver_address) + strlen(receiver_postal) + strlen(json) + ORDER_INSURANCE + ORDER_SUBTOTAL - 15 * strlen("%s") - 2 * strlen("%d") + 1); - sprintf(*post, ORDER_POST, prefix, order_number, service, (int)total_weight, sender_name, + sprintf(shipping.post, ORDER_POST, prefix, order_number, service, (int)total_weight, sender_name, sender_phone, origin, sender_address, sender_postal, receiver_name, receiver_phone, destination, receiver_address, receiver_postal, json, total_weight < 1000.0 ? "true" : "false", subtotal < 1000.0 ? 1000 : (int)subtotal); -} - -size_t anteraja_order_handle(const char *contents, size_t size, size_t nmemb, char **tracking_number) -{ - size_t realsize = size * nmemb; - handle(ORDER, contents, realsize, status_trail, (const char *[]){ - "content", - "waybill_no", - NULL - }, NULL, tracking_number); - return realsize; + static const char *trail[] = { + "content", + "waybill_no", + NULL + }; + shipping.trail = trail; } void anteraja_cleanup() diff --git a/common.h b/common.h deleted file mode 100644 index bef5e73..0000000 --- a/common.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifdef DEBUG -#include <stdio.h> -#endif -#include <string.h> -#include <curl/curl.h> -#include <json.h> -#include "pikul.h" - -extern struct shipping { - enum pikul_company company; - char *base; - struct curl_slist *headers; -} shipping; -extern json_tokener *tokener; - -void recurse(struct json_object *, const char *[], struct json_object **); - -enum type { SERVICES, ORDER }; - -inline void headers(const char *fields[], char *provisions[]) -{ - shipping.headers = NULL; - while (*fields) { - char header[strlen(*fields) + strlen(*provisions) + 2]; - sprintf(header, "%s:%s", *fields++, *provisions++); - shipping.headers = curl_slist_append(shipping.headers, header); - } -} - -inline void handle(enum type type, const char *contents, size_t num_bytes, const char *status_trail[], - const char *trail[], const char *attributes[], void *data) -{ -#ifdef DEBUG - ((char *)contents)[num_bytes] = '\0'; - fprintf(stderr, "%s\n", contents); -#endif - json_object *response = json_tokener_parse_ex(tokener, contents, num_bytes); - enum json_tokener_error error = json_tokener_get_error(tokener); - if (!response) { - if (error == json_tokener_continue) - return; - else { - json_tokener_reset(tokener); - return; - } - } else if (!json_object_is_type(response, json_type_object) || error != json_tokener_success) - return; - struct json_object *status = NULL; - recurse(response, status_trail, &status); - if (json_object_get_int(status) != 200) - return; - switch (type) { - case SERVICES: - ; - struct json_object *array = NULL; - recurse(response, trail, &array); - size_t length = json_object_array_length(array); - struct pikul_services **services = (struct pikul_services **)data; - *services = malloc(sizeof(struct pikul_services) - + sizeof(struct pikul_service *[length])); - (*services)->length = length; - enum { CODE, NAME, ETD, COST }; - for (size_t i = 0; i < length; i++) { - (*services)->list[i] = malloc(sizeof(struct pikul_service)); - struct pikul_service *service = (*services)->list[i]; - json_object *object = json_object_array_get_idx(array, i); - struct json_object_iterator iterator = json_object_iter_begin(object); - struct json_object_iterator iterator_end = json_object_iter_end(object); - while (!json_object_iter_equal(&iterator, &iterator_end)) { - const char *name = json_object_iter_peek_name(&iterator); - json_object *value = json_object_iter_peek_value(&iterator); - if (!strcmp(name, attributes[COST])) - service->cost = json_object_get_double(value); - else { - int len = json_object_get_string_len(value); - if (len) { - char *string = malloc(len + 1); - strcpy(string, json_object_get_string(value)); - if (!strcmp(name, attributes[CODE])) - service->code = string; - else if (!strcmp(name, attributes[NAME])) - service->name = string; - else if (!strcmp(name, attributes[ETD])) - service->etd = string; - } - } - json_object_iter_next(&iterator); - } - } - break; - case ORDER: - ; - struct json_object *string = NULL; - recurse(response, trail, &string); - char **tracking_number = (char **)data; - *tracking_number = malloc(json_object_get_string_len(string) + 1); - strcpy(*tracking_number, json_object_get_string(string)); - break; - default: - break; - } -} @@ -1,87 +1,165 @@ -#include "common.h" +#ifdef DEBUG +#include <stdio.h> +#endif +#include <string.h> +#include <json.h> +#include "private.h" CURL *curl; json_tokener *tokener; struct shipping shipping; -void headers(const char *[], char *[]); -void handle(enum type, const char *, size_t, const char *[], const char *[], const char *[], void *); - -void anteraja_init(char *[]); -void anteraja_services(const char *, const char *, double, char **, char **); -size_t anteraja_services_handle(const char *, size_t, size_t, struct pikul_services **); +const char **anteraja_init(char *[]); +const char **anteraja_services(const char *, const char *, double); void anteraja_order(const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, const char *, int, - char **[], double, char **, char **); -size_t anteraja_order_handle(const char *, size_t size, size_t nmemb, char **); + char **[], double); void anteraja_cleanup(); -void sicepat_init(char *[]); -void sicepat_services(const char *, const char *, double, char **); -size_t sicepat_services_handle(const char *, size_t, size_t, struct pikul_services **); +const char **sicepat_init(char *[]); +const char **sicepat_services(const char *, const char *, double); + +static void recurse(struct json_object *outer, const char *trail[], struct json_object **last) +{ + struct json_object *inner = NULL; + json_object_object_get_ex(outer, *trail, &inner); + if (*++trail) + recurse(inner, trail, last); + else + *last = inner; +} + +static size_t handle(char *contents, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; +#ifdef DEBUG + contents[realsize] = '\0'; + fprintf(stderr, "%s\n", contents); +#endif + json_object *response = json_tokener_parse_ex(tokener, contents, realsize); + enum json_tokener_error error = json_tokener_get_error(tokener); + if (!response) { + if (error == json_tokener_continue) + return realsize; + else { + json_tokener_reset(tokener); + return realsize; + } + } else if (!json_object_is_type(response, json_type_object) || error != json_tokener_success) + return realsize; + struct json_object *status = NULL; + recurse(response, shipping.status_trail, &status); + if (json_object_get_int(status) != 200) + return realsize; + switch (shipping.mode) { + case SERVICES: + ; + struct json_object *array = NULL; + recurse(response, shipping.trail, &array); + size_t length = json_object_array_length(array); + shipping.data = malloc(sizeof(struct pikul_services) + + sizeof(struct pikul_service *[length])); + struct pikul_services *services = (struct pikul_services *)shipping.data; + services->length = length; + const char **attributes = (const char **)data; + enum { CODE, NAME, ETD, COST }; + for (size_t i = 0; i < length; i++) { + services->list[i] = malloc(sizeof(struct pikul_service)); + struct pikul_service *service = services->list[i]; + json_object *object = json_object_array_get_idx(array, i); + struct json_object_iterator iterator = json_object_iter_begin(object); + struct json_object_iterator iterator_end = json_object_iter_end(object); + while (!json_object_iter_equal(&iterator, &iterator_end)) { + const char *name = json_object_iter_peek_name(&iterator); + json_object *value = json_object_iter_peek_value(&iterator); + if (!strcmp(name, attributes[COST])) + service->cost = json_object_get_double(value); + else { + int len = json_object_get_string_len(value); + if (len) { + char *string = malloc(len + 1); + strcpy(string, json_object_get_string(value)); + if (!strcmp(name, attributes[CODE])) + service->code = string; + else if (!strcmp(name, attributes[NAME])) + service->name = string; + else if (!strcmp(name, attributes[ETD])) + service->etd = string; + } + } + json_object_iter_next(&iterator); + } + } + break; + case ORDER: + ; + struct json_object *string = NULL; + recurse(response, shipping.trail, &string); + shipping.data = malloc(json_object_get_string_len(string) + 1); + strcpy(shipping.data, json_object_get_string(string)); + break; + default: + break; + } + return realsize; +} void pikul_init(enum pikul_company company, char *provisions[]) { curl_global_init(CURL_GLOBAL_SSL); curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle); #ifdef DEBUG curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif shipping.company = company; + shipping.headers = NULL; + const char **fields; switch (company) { case PIKUL_ANTERAJA: - anteraja_init(provisions); + fields = anteraja_init(provisions); break; case PIKUL_SICEPAT: - sicepat_init(provisions); + fields = sicepat_init(provisions); break; default: break; } + while (*fields) { + char header[strlen(*fields) + strlen(":") + strlen(*provisions) + 1]; + sprintf(header, "%s:%s", *fields++, *provisions++); + shipping.headers = curl_slist_append(shipping.headers, header); + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, shipping.headers); tokener = json_tokener_new(); } -void recurse(struct json_object *outer, const char *trail[], struct json_object **last) -{ - struct json_object *inner = NULL; - json_object_object_get_ex(outer, *trail, &inner); - if (*++trail) - recurse(inner, trail, last); - else - *last = inner; -} - struct pikul_services *pikul_services(const char *origin, const char *destination, double weight) { - struct pikul_services *services = NULL; - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &services); - char *url; - char *post = NULL; - size_t (*handler)(const char *, size_t, size_t, struct pikul_services **); + shipping.post = NULL; + const char **attributes; switch (shipping.company) { case PIKUL_ANTERAJA: - anteraja_services(origin, destination, weight, &url, &post); - handler = anteraja_services_handle; + attributes = anteraja_services(origin, destination, weight); break; case PIKUL_SICEPAT: - sicepat_services(origin, destination, weight, &url); - handler = sicepat_services_handle; + attributes = sicepat_services(origin, destination, weight); break; default: break; } - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handler); - if (post) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post); + curl_easy_setopt(curl, CURLOPT_URL, shipping.url); + if (shipping.post) + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, shipping.post); else curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); + shipping.mode = SERVICES; + curl_easy_setopt(curl, CURLOPT_WRITEDATA, attributes); curl_easy_perform(curl); - if (post) - free(post); - free(url); - return services; + if (shipping.post) + free(shipping.post); + free(shipping.url); + return (struct pikul_services *)shipping.data; } static inline void free_service(struct pikul_service *service) @@ -130,33 +208,28 @@ char *pikul_order(const char *order_number, const char *service, const char *sen const char *destination, const char *receiver_address, const char *receiver_postal, int nitems, char **items[], double subtotal) { - char *tracking_number = NULL; - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &tracking_number); - char *url; - char *post = NULL; - size_t (*handler)(const char *, size_t, size_t, char **); + shipping.post = NULL; switch (shipping.company) { case PIKUL_ANTERAJA: anteraja_order(order_number, service, sender_name, sender_phone, origin, sender_address, sender_postal, receiver_name, receiver_phone, destination, receiver_address, receiver_postal, nitems, items, - subtotal, &url, &post); - handler = anteraja_order_handle; + subtotal); break; default: break; } - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handler); - if (post) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post); + curl_easy_setopt(curl, CURLOPT_URL, shipping.url); + if (shipping.post) + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, shipping.post); else curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L); + shipping.mode = ORDER; curl_easy_perform(curl); - if (post) - free(post); - free(url); - return tracking_number; + if (shipping.post) + free(shipping.post); + free(shipping.url); + return (char *)shipping.data; } void pikul_cleanup() diff --git a/private.h b/private.h new file mode 100644 index 0000000..6df3e91 --- /dev/null +++ b/private.h @@ -0,0 +1,17 @@ +#include <curl/curl.h> +#include "pikul.h" + +extern struct shipping { + enum pikul_company company; + char *base; + struct curl_slist *headers; + const char **status_trail; + char *url; + char *post; + enum { + SERVICES, + ORDER + } mode; + const char **trail; + void *data; +} shipping; @@ -1,42 +1,41 @@ -#include "common.h" +#include <stdlib.h> +#include <string.h> +#include "private.h" #define BASE "http://api.sicepat.com/customer/" -static const char *status_trail[] = { - "sicepat", - "status", - "code", - NULL -}; - -void sicepat_init(char *provisions[]) +const char **sicepat_init(char *provisions[]) { shipping.base = malloc(strlen(BASE) + 1); strcpy(shipping.base, BASE); - headers((const char *[]){ "api-key", NULL }, provisions); + static const char *status_trail[] = { + "sicepat", + "status", + "code", + NULL + }; + shipping.status_trail = status_trail; + static const char *fields[] = { "api-key", NULL }; + return fields; } -void sicepat_services(const char *origin, const char *destination, double weight, char **url) +const char **sicepat_services(const char *origin, const char *destination, double weight) { - *url = malloc(strlen(shipping.base) + strlen("tariff?origin=") + strlen(origin) + shipping.url = malloc(strlen(shipping.base) + strlen("tariff?origin=") + strlen(origin) + strlen("&destination=") + strlen(destination) + strlen("&weight=") + 9); - sprintf(*url, "%stariff?origin=%s&destination=%s&weight=%f", shipping.base, origin, destination, - weight); -} - -size_t sicepat_services_handle(const char *contents, size_t size, size_t nmemb, - struct pikul_services **services) -{ - size_t realsize = size * nmemb; - handle(SERVICES, contents, realsize, status_trail, (const char *[]){ - "sicepat", - "results", - NULL - }, (const char *[]){ - "service", - "description", - "etd", - "tariff" - }, services); - return realsize; + sprintf(shipping.url, "%stariff?origin=%s&destination=%s&weight=%f", shipping.base, origin, + destination, weight); + static const char *trail[] = { + "sicepat", + "results", + NULL + }; + shipping.trail = trail; + static const char *attributes[] = { + "service", + "description", + "etd", + "tariff" + }; + return attributes; } |