taler-mdb

GNU Taler Extensions and Integrations
Log | Files | Refs | Submodules | README | LICENSE

commit b608bf09e50e71fdc6320bfc33cfea5cf2db5ade
parent a02a3a4b5b706e23c2f8cb2f34c463c5a1800733
Author: BOSS_Marco <bossm8@students.bfh.ch>
Date:   Thu, 31 Oct 2019 17:43:52 +0100

fixes

Diffstat:
Msrc/communication.c | 351++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/configuration.h | 11++++++++---
Msrc/main.c | 42+++++++++++++++++++++---------------------
Msrc/nfc.c | 22++++++++++++----------
Msrc/product.c | 60++++++++++++++++++++++++++++++++++--------------------------
5 files changed, 262 insertions(+), 224 deletions(-)

diff --git a/src/communication.c b/src/communication.c @@ -33,216 +33,239 @@ along with int taler_init(CURL **curl) { - if( *curl != NULL ){ - printf( "taler_init: curl handle already initialized\n" ); - return EXIT_FAILURE; - } - - // initialize curl - CURLcode result = curl_global_init( CURL_GLOBAL_ALL ); - *curl = curl_easy_init(); - if( !(*curl) || result != CURLE_OK ){ - printf( "taler_init: could not inizialize curl handle\n" ); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + CURLcode result; + + if( *curl != NULL ){ + printf( "taler_init: curl handle already initialized\n" ); + return EXIT_FAILURE; + } + + /* initialize curl */ + result = curl_global_init( CURL_GLOBAL_ALL ); + *curl = curl_easy_init(); + if( !(*curl) || result != CURLE_OK ){ + printf( "taler_init: could not inizialize curl handle\n" ); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; } void taler_exit( CURL **curl ) { - curl_easy_cleanup(*curl); - curl_global_cleanup(); + curl_easy_cleanup(*curl); + curl_global_cleanup(); } int taler_alloc_string( char **string, size_t size ) { - *string = malloc( size ); - if( !(*string) ){ - printf( "taler_alloc: unable to allocate string" ); - exit( EXIT_FAILURE ); - } - return EXIT_SUCCESS; + *string = malloc( size ); + if( !(*string) ){ + printf( "taler_alloc: unable to allocate string" ); + exit( EXIT_FAILURE ); + } + return EXIT_SUCCESS; } -static size_t _taler_write_response( void *contents, size_t size, size_t nmemb, void *userp ) +static size_t _taler_write_response( void *contents, size_t size, size_t nmemb, + void *userp ) { - size_t realSize = size * nmemb; - struct TalerResponse *response = (struct TalerResponse *)userp; - - char *tempString = realloc( response->string, response->size + realSize + 1 ); - if( !tempString ) { - printf( "Allocation failure" ); - return EXIT_FAILURE; - } - - response->string = tempString; - memcpy(&( response->string[response->size] ), contents, realSize ); - response->size += realSize; - response->string[response->size] = 0; - - return realSize; + char *tempString; + size_t realSize = size * nmemb; + struct TalerResponse *response = (struct TalerResponse *)userp; + + tempString = realloc( response->string, response->size + realSize + 1 ); + if( !tempString ) { + printf( "Allocation failure" ); + return EXIT_FAILURE; + } + + response->string = tempString; + memcpy(&( response->string[response->size] ), contents, realSize ); + response->size += realSize; + response->string[response->size] = 0; + + return realSize; } int taler_create_order_req( ProductOrder *product ) { - // create the string representing the amount, e.g. "KUDOS:2.5" ( +2 because of ':' and '\0' ) - char amountStr[ strlen(product->currency) + strlen(product->amount) + 2 ]; - sprintf( amountStr, "%s:%s", product->currency, product->amount ); - - // create the fulfillment ur, e.g. "taler://fulfillment-success/Enjoy+your+ice+cream!"; ( +2 because of '!' and '\0' ) - char fulfillmentUrl[ strlen(FULLFILLMENT_URL) + strlen(FULLFILLMENT_MSG) + strlen(product->product) + 2 ]; - sprintf( fulfillmentUrl, "%s%s%s!", FULLFILLMENT_URL, FULLFILLMENT_MSG, product->product ); - - // create the json object for the order request - json_t *orderReq = json_pack( "{ s: { s:s, s:s, s:s }}", "order", "summary", product->product, "amount", amountStr, "fulfillment_url", fulfillmentUrl ); - if( !orderReq ){ - printf( "taler_create_order_req: error creating json object\n" ); - return EXIT_FAILURE; - } - - // create the string to send to taler in compact format - char *buffer = json_dumps( orderReq, JSON_COMPACT ); - if( !buffer ){ - printf("taler_create_order_req: error converting json to string\n"); - return EXIT_FAILURE; - } - - // allocate memory for the string and copy it into the product - char* temp = realloc( product->orderRequest, strlen(buffer) + 1 ); - if( !temp ){ - printf( "could not allocate order\n" ); - return EXIT_FAILURE; - } - product->orderRequest = temp; - strcpy( product->orderRequest, buffer ); - - // print the created order request and free the json object - printf( "Created order Request: \n" ); - json_dumpf( orderReq, stdout, JSON_INDENT(2) ); - printf("\n"); - json_delete( orderReq ); - - // free the allocated buffer from json_dumps - free( buffer ); - - return EXIT_SUCCESS; + json_t *orderReq; + char* temp; + + /* create the string representing the amount, e.g. "KUDOS:2.5" ( +2 because of ':' and '\0' ) */ + char amountStr[ strlen(product->currency) + strlen(product->amount) + 2 ]; + /* create the fulfillment ur, e.g. "taler://fulfillment-success/Enjoy+your+ice+cream!"; ( +2 because of '!' and '\0' ) */ + char fulfillmentUrl[ strlen(FULLFILLMENT_URL) + strlen(FULLFILLMENT_MSG) + + strlen(product->product) + 2 ]; + + /* create the strings declared earlier */ + sprintf( amountStr, "%s:%s", product->currency, product->amount ); + sprintf( fulfillmentUrl, "%s%s%s!", FULLFILLMENT_URL, FULLFILLMENT_MSG, + product->product ); + + /* create the json object for the order request */ + orderReq = json_pack( "{ s: { s:s, s:s, s:s }}", JSON_REQ_ORDER, + JSON_REQ_SUMMARY, product->product, JSON_REQ_AMOUNT, + amountStr, JSON_REQ_FULFILLMENT, fulfillmentUrl ); + if( !orderReq ){ + printf( "taler_create_order_req: error creating json object\n" ); + return EXIT_FAILURE; + } + + /* create the string to send to taler in compact format */ + char *buffer = json_dumps( orderReq, JSON_COMPACT ); + if( !buffer ){ + printf("taler_create_order_req: error converting json to string\n"); + return EXIT_FAILURE; + } + + /* allocate memory for the string and copy it into the product */ + temp = realloc( product->orderRequest, strlen(buffer) + 1 ); + if( !temp ){ + printf( "could not allocate order\n" ); + return EXIT_FAILURE; + } + product->orderRequest = temp; + strcpy( product->orderRequest, buffer ); + + /* print the created order request and free the json object */ + printf( "Created order Request: \n" ); + json_dumpf( orderReq, stdout, JSON_INDENT(2) ); + printf("\n"); + json_decref( orderReq ); + + /* free the allocated buffer from json_dumps */ + free( buffer ); + + return EXIT_SUCCESS; } int taler_create_order( CURL *curl, ProductOrder *product ) { - // reset the response size - product->response->size = 0; + char url[ strlen(BACKEND_BASE_URL) + strlen( ORDER ) + 1 ]; + struct curl_slist *list = NULL; + CURLcode result; + + /* reset the response size */ + product->response->size = 0; - // set the url - char url[ strlen(BACKEND_BASE_URL) + strlen( ORDER ) + 1 ]; - sprintf( url, "%s%s", BACKEND_BASE_URL, ORDER ); - curl_easy_setopt( curl, CURLOPT_URL, url ); + /* set the url */ + sprintf( url, "%s%s", BACKEND_BASE_URL, ORDER ); + curl_easy_setopt( curl, CURLOPT_URL, url ); - // set the authentication headers - struct curl_slist *list = NULL; - list = curl_slist_append( list, AUTH_HEADER ); - curl_easy_setopt( curl, CURLOPT_HTTPHEADER, list ); + /* set the authentication headers */ + list = curl_slist_append( list, AUTH_HEADER ); + curl_easy_setopt( curl, CURLOPT_HTTPHEADER, list ); - // curl option "post" - curl_easy_setopt( curl, CURLOPT_HTTPPOST, true ); - curl_easy_setopt( curl, CURLOPT_POSTFIELDS, product->orderRequest ); + /* curl option "post" */ + curl_easy_setopt( curl, CURLOPT_HTTPPOST, true ); + curl_easy_setopt( curl, CURLOPT_POSTFIELDS, product->orderRequest ); - // pass the write function and the struct to write to - curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, _taler_write_response ); - curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)product->response ); + /* pass the write function and the struct to write to */ + curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, _taler_write_response ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)product->response ); - // perform the call - CURLcode result = curl_easy_perform( curl ); - if( result != CURLE_OK ){ - printf( "could not communicate with \"%s\"\n", url ); - return EXIT_FAILURE; - } + /* perform the call */ + result = curl_easy_perform( curl ); + if( result != CURLE_OK ){ + printf( "could not communicate with \"%s\"\n", url ); + return EXIT_FAILURE; + } - // reset the curl options - curl_easy_reset( curl ); + /* reset the curl options */ + curl_easy_reset( curl ); - // clean up - curl_slist_free_all( list ); + /* clean up */ + curl_slist_free_all( list ); - printf("%s\n", product->response->string ); + printf("%s\n", product->response->string ); - return EXIT_SUCCESS; + return EXIT_SUCCESS; } int taler_check_payment_status( CURL *curl, ProductOrder *product ) { - // reset the response size - product->response->size = 0; + struct curl_slist *list = NULL; + CURLcode result; - // set the url - curl_easy_setopt( curl, CURLOPT_URL, product->checkUrl ); + /* reset the response size */ + product->response->size = 0; - // set the authentication headers - struct curl_slist *list = NULL; - list = curl_slist_append( list, AUTH_HEADER ); - curl_easy_setopt( curl, CURLOPT_HTTPHEADER, list ); + /* set the url */ + curl_easy_setopt( curl, CURLOPT_URL, product->checkUrl ); - // curl option "get" - curl_easy_setopt( curl, CURLOPT_HTTPGET, true ); + /* set the authentication headers */ + list = curl_slist_append( list, AUTH_HEADER ); + curl_easy_setopt( curl, CURLOPT_HTTPHEADER, list ); - // pass the write function and the struct to write to - curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, _taler_write_response ); - curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)product->response ); + /* curl option "get" */ + curl_easy_setopt( curl, CURLOPT_HTTPGET, true ); - // perform the call - CURLcode result = curl_easy_perform(curl); - if( result != CURLE_OK ){ - printf( "could not communicate with \"%s\"\n", product->checkUrl ); - return EXIT_FAILURE; - } + /* pass the write function and the struct to write to */ + curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, _taler_write_response ); + curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)product->response ); - // reset the curl options - curl_easy_reset( curl ); + /* perform the call */ + result = curl_easy_perform(curl); + if( result != CURLE_OK ){ + printf( "could not communicate with \"%s\"\n", product->checkUrl ); + return EXIT_FAILURE; + } - // clean up - curl_slist_free_all( list ); + /* reset the curl options */ + curl_easy_reset( curl ); - return EXIT_SUCCESS; + /* clean up */ + curl_slist_free_all( list ); + + return EXIT_SUCCESS; } -int taler_parse_json( const TalerResponse *response, const char *memberName, char **returnStr ) +int taler_parse_json( const TalerResponse *response, const char *memberName, + char **returnStr ) { - if( !(*returnStr) ) - taler_alloc_string( returnStr, 1 ); - - json_error_t error; - json_t *root = NULL; - root = json_loads( response->string, JSON_DISABLE_EOF_CHECK, &error ); - if( !root ){ - printf("taler_parse_json: %s\n", error.text ); - return EXIT_FAILURE; - } - - char *result = NULL; - if( json_unpack( root, "{s:s}", memberName, &result ) < 0 ){ - printf( "taler_parse_json: no member named \"%s\" found!\n", memberName ); - json_decref( root ); - return EXIT_FAILURE; - } - if( !result ){ - printf( "taler_parse_json: no member named \"%s\" found!\n", memberName ); - json_decref( root ); - return EXIT_FAILURE; - } - char *temp = NULL; - temp = realloc( *returnStr, strlen(result) + 1 ); - if( !temp ){ - printf( "taler_parse_json: could not allocate memory for member\n" ); - json_decref( root ); - return EXIT_FAILURE; - } - *returnStr = temp; - strcpy( *returnStr, result ); + /* json variables */ + json_error_t error; + json_t *root = NULL; + + char *temp = NULL; + + /* if the provided string was not allocated before allocate initial size 1 to + * realloc later */ + if( !(*returnStr) ) + taler_alloc_string( returnStr, 1 ); + + /* load the json with th string provided from taler in the response struct */ + root = json_loads( response->string, JSON_DISABLE_EOF_CHECK, &error ); + if( !root ){ + printf("taler_parse_json: %s\n", error.text ); + return EXIT_FAILURE; + } + char *result = NULL; + if( json_unpack( root, "{s:s}", memberName, &result ) < 0 ){ + printf( "taler_parse_json: no member named \"%s\" found!\n", memberName ); + json_decref( root ); + return EXIT_FAILURE; + } + if( !result ){ + printf( "taler_parse_json: no member named \"%s\" found!\n", memberName ); + json_decref( root ); + return EXIT_FAILURE; + } + + temp = realloc( *returnStr, strlen(result) + 1 ); + if( !temp ){ + printf( "taler_parse_json: could not allocate memory for member\n" ); json_decref( root ); + return EXIT_FAILURE; + } + *returnStr = temp; + strcpy( *returnStr, result ); - return EXIT_SUCCESS; + json_decref( root ); + return EXIT_SUCCESS; } diff --git a/src/configuration.h b/src/configuration.h @@ -44,14 +44,19 @@ static const char*const JSON_PAID = "paid"; static const char*const JSON_PAY_URI = "taler_pay_uri"; static const char*const JSON_ORDER_ID = "order_id"; +/* json order request keys */ +static const char*const JSON_REQ_ORDER = "order"; +static const char*const JSON_REQ_SUMMARY = "summary"; +static const char*const JSON_REQ_AMOUNT = "amount"; +static const char*const JSON_REQ_FULFILLMENT = "fulfillment_url"; -// New AID +/* New AID */ // static uint8_t taler_aid[] = { 0xF0, 0x00, 0x54, 0x41, 0x4c, 0x45, 0x52 }; -// Demo AID until uptade +/* Demo AID until uptade */ static const uint8_t taler_aid[] = { 0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 }; -// APDU commands +/* APDU commands */ #define APDU_SUCCESS "\x90\x00" static const uint8_t select_file[] = { 0x00, 0xA4, 0x04, 0x00, 0x07 }; static const uint8_t put_data[] = { 0x00, 0xDA, 0x01, 0x00, 0x7c, 0x01 }; diff --git a/src/main.c b/src/main.c @@ -45,14 +45,14 @@ nfc_context *context = NULL; void *start_nfc_transmission (void *ignored) { - // supress warning about unused variable + /* supress warning about unused variable */ (void) ignored; if ( pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0 ) { printf ("Error setting thread cancelling type\n"); } - // start endless transmission loop (until threads gets cancelled) + /* start endless transmission loop (until threads gets cancelled) */ while ( 1 ) { if ( pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) != 0 ) @@ -72,7 +72,7 @@ void *start_nfc_transmission (void *ignored) int main ( ) { - // initialize nfc + /* initialize nfc */ nfc_init (&context); if ( ! context ) { @@ -80,7 +80,7 @@ int main ( ) return EXIT_FAILURE; } - // inizialize taler + /* inizialize taler */ CURL *curl = NULL; if ( taler_init (&curl) ) { @@ -88,7 +88,7 @@ int main ( ) return EXIT_FAILURE; } - // inizialize product + /* inizialize product */ if ( product_init (&product, CURRENCY) ) { printf ("Unable to init product\n"); @@ -103,32 +103,32 @@ int main ( ) if ( getchar () == 'x' ) break; - // DEMO snickers + /* DEMO snickers */ product.amount = "0.1"; product.product = "Snickers"; - // create the order request + /* create the order request */ taler_create_order_req (&product); - // create the order + /* create the order */ while ( taler_create_order (curl, &product) ) ; - // store the order id into the struct + /* store the order id into the struct */ product_set_order_id (&product); - // store the url to check wheter the payment happened or not + /* store the url to check wheter the payment happened or not */ product_set_check_url (&product); - // check the payment status for the first time + /* check the payment status for the first time */ while ( taler_check_payment_status (curl, &product) ) ; - // store the url to pay, to do this task the payment status has to be called before, because the url will be in the response + /* store the url to pay, to do this task the payment status has to be called before, because the url will be in the response */ product_set_pay_url (&product); - // start a thread to send payment request to taler wallet + /* start a thread to send payment request to taler wallet */ pthread_t nfcThread; if ( pthread_create (&nfcThread, NULL, start_nfc_transmission, NULL) ) { @@ -136,7 +136,7 @@ int main ( ) return EXIT_FAILURE; } - // check the payment status, if paid exit while loop and end thread transmitting nfc messages + /* check the payment status, if paid exit while loop and end thread transmitting nfc messages */ while ( ! product.paid ) { printf ("Order payment processing\n"); @@ -144,7 +144,7 @@ int main ( ) sleep (5); while ( taler_check_payment_status (curl, &product) ) ; - // set the boolean paid member of ProductOrder struct + /* set the boolean paid member of ProductOrder struct */ product_set_paid_status (&product); printf ("Payment status paid: %s\n\n", (product.paid ? "true" : "false") ); @@ -152,12 +152,12 @@ int main ( ) printf ("Order no.: %s paid!\n\n", product.orderID); - // ----------------- - // Here comes the code for releasing the product - // ----------------- + /* ----------------- + Here comes the code for releasing the product + ----------------- */ - // send cancel request to nfc thread + /* send cancel request to nfc thread */ while ( pthread_cancel (nfcThread) != 0 ) { printf ("Error sending cancel request to thread for nfc transmission"); @@ -175,12 +175,12 @@ int main ( ) fflush (stdout); } - // reset the product + /* reset the product */ product_reset (&product); } - // clear all initialized data + /* clear all initialized data */ nfc_exit (context); product_exit (&product); taler_exit (&curl); diff --git a/src/nfc.c b/src/nfc.c @@ -30,7 +30,7 @@ along with #include "wallet.h" -// upper and lower bounds for mifare targets uid length +/* upper and lower bounds for mifare targets uid length */ #define UID_LEN_UPPER 7 #define UID_LEN_LOWER 4 @@ -38,6 +38,7 @@ along with int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize) { nfc_device *pnd = NULL; + nfc_target nt; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MEMORY LEAK? NFC OPEN? @@ -49,7 +50,7 @@ int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize) return EXIT_FAILURE; } - // initialize device as reader + /* initialize device as reader */ if ( nfc_initiator_init (pnd) < 0 ) { nfc_perror (pnd, "nfc_initiator_init"); @@ -60,9 +61,7 @@ int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize) printf ("Device %s opened: '%s'\n\n", nfc_device_get_name (pnd), nfc_device_get_connstring (pnd) ); - nfc_target nt; - - // connect to a target device + /* connect to a target device */ if ( nfc_connect_target (pnd, &nt) ) { nfc_close (pnd); @@ -70,15 +69,15 @@ int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize) } ; - // send the message to the wallet + /* send the message to the wallet */ if ( wallet_transmit (pnd, talerPayUrl, urlSize) ) { - // the transmition failed, the target has to be reselected when using MIFARE as defined in libnfc --> exit + /* the transmition failed, the target has to be reselected when using MIFARE as defined in libnfc --> exit */ nfc_close (pnd); return EXIT_FAILURE; } - // clean up + /* clean up */ nfc_initiator_deselect_target (pnd); nfc_close (pnd); @@ -87,16 +86,19 @@ int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize) int nfc_connect_target (nfc_device *pnd, nfc_target *nt) { + /* ctr for how many tries to connect a target */ + int ctr = 2; + const nfc_modulation nmMifare[] = { { .nmt = NMT_ISO14443A, .nbr = NBR_106, } }; printf ("nfc_connect_target: trying to connect to target\n"); - int ctr = 2; + while ( ctr > 0 ) { - // set uid lenght to zero ( in case of second selecting the length still has the old value ) + /* set uid lenght to zero ( in case of second selecting the length still has the old value ) */ nt->nti.nai.szUidLen = 0; if ( nfc_initiator_select_passive_target (pnd, nmMifare[0], NULL, 0, nt) <= 0 ) diff --git a/src/product.c b/src/product.c @@ -47,7 +47,8 @@ int product_init (ProductOrder *product, const char *currency) return EXIT_FAILURE; } - // malloc for every string member with size 1, every other func just calls realloc, because this struct gets used over and over again + /* malloc for every string member with size 1, every other func just calls + * realloc, because this struct gets used over and over again */ product->response = malloc (sizeof(TalerResponse) ); if ( ! product->response ) { @@ -120,31 +121,38 @@ int product_set_pay_url (ProductOrder *product) int product_set_paid_status (ProductOrder *product) { - json_error_t error; - json_t *root = NULL; - root = json_loads( product->response->string, JSON_DISABLE_EOF_CHECK, &error ); - if( !root ){ - printf("taler_parse_json: %s\n", error.text ); - return EXIT_FAILURE; - } - - // extract the boolean value of paid out of the json object - int b = -1; - if ( json_unpack( root, "{s:b}", JSON_PAID, &b ) < 0 ){ - printf("taler_parse_json: no value \"%s\" found!\n", JSON_PAID ); - json_decref( root ); - return EXIT_FAILURE; - } - - json_decref(root); - - // set the paid status to true or false - if( b == true || b == false ){ - product->paid = b; - }else{ - printf( "product_set_paid_status: json parsing failed\n" ); - return EXIT_FAILURE; - } + json_error_t error; + json_t *root = NULL; + + /* variable to extract the boolean value out of json object */ + int b = -1; + + root = json_loads( product->response->string, JSON_DISABLE_EOF_CHECK, &error); + if( !root ) + { + printf("taler_parse_json: %s\n", error.text ); + return EXIT_FAILURE; + } + + /* extract the boolean value of paid out of the json object */ + if ( json_unpack( root, "{s:b}", JSON_PAID, &b ) < 0 ) + { + printf("taler_parse_json: no value \"%s\" found!\n", JSON_PAID ); + json_decref( root ); + return EXIT_FAILURE; + } + + json_decref(root); + + /* set the paid status to true or false */ + if( b == true || b == false ) + { + product->paid = b; + }else + { + printf( "product_set_paid_status: json parsing failed\n" ); + return EXIT_FAILURE; + } return EXIT_SUCCESS; }