@@ -600,120 +600,60 @@ int network_extract_query_param (const char *query, const char *key, char *outpu
600600 return -3 ; // Key not found
601601}
602602
603- bool network_compute_endpoints (sqlite3_context * context , network_data * data , const char * conn_string ) {
604- // JSON format: {"address":"https://host:port","database":"db.sqlite","projectID":"abc","organizationID":"org","apikey":"KEY"}
605- bool result = false;
606- size_t conn_len = strlen (conn_string );
607-
608- char * address = json_extract_string (conn_string , conn_len , "address" );
609- char * database = json_extract_string (conn_string , conn_len , "database" );
610- char * project_id = json_extract_string (conn_string , conn_len , "projectID" );
611- char * org_id = json_extract_string (conn_string , conn_len , "organizationID" );
612- char * apikey = json_extract_string (conn_string , conn_len , "apikey" );
613- char * token = json_extract_string (conn_string , conn_len , "token" );
614-
615- char * authentication = NULL ;
616- char * check_endpoint = NULL ;
617- char * upload_endpoint = NULL ;
618- char * apply_endpoint = NULL ;
619- char * status_endpoint = NULL ;
620-
621- // validate mandatory fields
622- if (!address || !database || !project_id || !org_id ) {
623- sqlite3_result_error (context , "JSON must contain address, database, projectID, and organizationID" , -1 );
603+ static bool network_compute_endpoints_with_address (sqlite3_context * context , network_data * data , const char * address , const char * managedDatabaseId ) {
604+ if (!managedDatabaseId || managedDatabaseId [0 ] == '\0' ) {
605+ sqlite3_result_error (context , "managedDatabaseId cannot be empty" , -1 );
624606 sqlite3_result_error_code (context , SQLITE_ERROR );
625- goto finalize ;
607+ return false ;
626608 }
627609
628- // parse address: scheme://host[:port]
629- const char * scheme_end = strstr (address , "://" );
630- if (!scheme_end ) {
631- sqlite3_result_error (context , "address must include scheme (e.g. https://host:port)" , -1 );
610+ if (!address || address [0 ] == '\0' ) {
611+ sqlite3_result_error (context , "address cannot be empty" , -1 );
632612 sqlite3_result_error_code (context , SQLITE_ERROR );
633- goto finalize ;
634- }
635-
636- size_t scheme_len = scheme_end - address ;
637- const char * host_start = scheme_end + 3 ;
638- const char * port_sep = strchr (host_start , ':' );
639- const char * host_end = port_sep ? port_sep : host_start + strlen (host_start );
640- const char * port_str = port_sep ? port_sep + 1 : CLOUDSYNC_DEFAULT_ENDPOINT_PORT ;
641-
642- // build authentication from apikey or token
643- if (apikey ) {
644- authentication = network_authentication_token ("apikey" , apikey );
645- } else if (token ) {
646- authentication = network_authentication_token ("token" , token );
613+ return false;
647614 }
648615
649- // build endpoints: {scheme}://{host}:{port}/ v2/cloudsync/{projectID}/{database }/{siteId}/{action}
650- size_t requested = scheme_len + 3 + ( host_end - host_start ) + 1 + strlen (port_str ) + 1
651- + strlen (CLOUDSYNC_ENDPOINT_PREFIX ) + 1 + strlen (project_id ) + 1
652- + strlen ( database ) + 1 + UUID_STR_MAXLEN + 1 + 16 ;
653- check_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
654- upload_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
655- apply_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
656- status_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
616+ // build endpoints: {address}/ v2/cloudsync/databases/{managedDatabaseId }/{siteId}/{action}
617+ size_t requested = strlen (address ) + 1
618+ + strlen (CLOUDSYNC_ENDPOINT_PREFIX ) + 1 + strlen (managedDatabaseId ) + 1
619+ + UUID_STR_MAXLEN + 1 + 16 ;
620+ char * check_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
621+ char * upload_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
622+ char * apply_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
623+ char * status_endpoint = (char * )cloudsync_memory_zeroalloc (requested );
657624
658625 if (!check_endpoint || !upload_endpoint || !apply_endpoint || !status_endpoint ) {
659626 sqlite3_result_error_code (context , SQLITE_NOMEM );
660- goto finalize ;
661- }
662-
663- // format: scheme://host:port/v2/cloudsync/projectID/database/siteId/action
664- snprintf (check_endpoint , requested , "%.*s://%.*s:%s/%s/%s/%s/%s/%s" ,
665- (int )scheme_len , address , (int )(host_end - host_start ), host_start , port_str ,
666- CLOUDSYNC_ENDPOINT_PREFIX , project_id , database , data -> site_id , CLOUDSYNC_ENDPOINT_CHECK );
667- snprintf (upload_endpoint , requested , "%.*s://%.*s:%s/%s/%s/%s/%s/%s" ,
668- (int )scheme_len , address , (int )(host_end - host_start ), host_start , port_str ,
669- CLOUDSYNC_ENDPOINT_PREFIX , project_id , database , data -> site_id , CLOUDSYNC_ENDPOINT_UPLOAD );
670- snprintf (apply_endpoint , requested , "%.*s://%.*s:%s/%s/%s/%s/%s/%s" ,
671- (int )scheme_len , address , (int )(host_end - host_start ), host_start , port_str ,
672- CLOUDSYNC_ENDPOINT_PREFIX , project_id , database , data -> site_id , CLOUDSYNC_ENDPOINT_APPLY );
673- snprintf (status_endpoint , requested , "%.*s://%.*s:%s/%s/%s/%s/%s/%s" ,
674- (int )scheme_len , address , (int )(host_end - host_start ), host_start , port_str ,
675- CLOUDSYNC_ENDPOINT_PREFIX , project_id , database , data -> site_id , CLOUDSYNC_ENDPOINT_STATUS );
676-
677- result = true;
678-
679- finalize :
680- if (result ) {
681- if (authentication ) {
682- if (data -> authentication ) cloudsync_memory_free (data -> authentication );
683- data -> authentication = authentication ;
684- }
685-
686- if (data -> org_id ) cloudsync_memory_free (data -> org_id );
687- data -> org_id = cloudsync_string_dup (org_id );
688-
689- if (data -> check_endpoint ) cloudsync_memory_free (data -> check_endpoint );
690- data -> check_endpoint = check_endpoint ;
691-
692- if (data -> upload_endpoint ) cloudsync_memory_free (data -> upload_endpoint );
693- data -> upload_endpoint = upload_endpoint ;
694-
695- if (data -> apply_endpoint ) cloudsync_memory_free (data -> apply_endpoint );
696- data -> apply_endpoint = apply_endpoint ;
697-
698- if (data -> status_endpoint ) cloudsync_memory_free (data -> status_endpoint );
699- data -> status_endpoint = status_endpoint ;
700- } else {
701- if (authentication ) cloudsync_memory_free (authentication );
702627 if (check_endpoint ) cloudsync_memory_free (check_endpoint );
703628 if (upload_endpoint ) cloudsync_memory_free (upload_endpoint );
704629 if (apply_endpoint ) cloudsync_memory_free (apply_endpoint );
705630 if (status_endpoint ) cloudsync_memory_free (status_endpoint );
631+ return false;
706632 }
707633
708- // cleanup JSON-extracted strings
709- if (address ) cloudsync_memory_free (address );
710- if (database ) cloudsync_memory_free (database );
711- if (project_id ) cloudsync_memory_free (project_id );
712- if (org_id ) cloudsync_memory_free (org_id );
713- if (apikey ) cloudsync_memory_free (apikey );
714- if (token ) cloudsync_memory_free (token );
634+ // format: {address}/v2/cloudsync/databases/{managedDatabaseID}/{siteId}/{action}
635+ snprintf (check_endpoint , requested , "%s/%s/%s/%s/%s" ,
636+ address , CLOUDSYNC_ENDPOINT_PREFIX , managedDatabaseId , data -> site_id , CLOUDSYNC_ENDPOINT_CHECK );
637+ snprintf (upload_endpoint , requested , "%s/%s/%s/%s/%s" ,
638+ address , CLOUDSYNC_ENDPOINT_PREFIX , managedDatabaseId , data -> site_id , CLOUDSYNC_ENDPOINT_UPLOAD );
639+ snprintf (apply_endpoint , requested , "%s/%s/%s/%s/%s" ,
640+ address , CLOUDSYNC_ENDPOINT_PREFIX , managedDatabaseId , data -> site_id , CLOUDSYNC_ENDPOINT_APPLY );
641+ snprintf (status_endpoint , requested , "%s/%s/%s/%s/%s" ,
642+ address , CLOUDSYNC_ENDPOINT_PREFIX , managedDatabaseId , data -> site_id , CLOUDSYNC_ENDPOINT_STATUS );
715643
716- return result ;
644+ if (data -> check_endpoint ) cloudsync_memory_free (data -> check_endpoint );
645+ data -> check_endpoint = check_endpoint ;
646+
647+ if (data -> upload_endpoint ) cloudsync_memory_free (data -> upload_endpoint );
648+ data -> upload_endpoint = upload_endpoint ;
649+
650+ if (data -> apply_endpoint ) cloudsync_memory_free (data -> apply_endpoint );
651+ data -> apply_endpoint = apply_endpoint ;
652+
653+ if (data -> status_endpoint ) cloudsync_memory_free (data -> status_endpoint );
654+ data -> status_endpoint = status_endpoint ;
655+
656+ return true;
717657}
718658
719659void network_result_to_sqlite_error (sqlite3_context * context , NETWORK_RESULT res , const char * default_error_message ) {
@@ -733,57 +673,60 @@ network_data *cloudsync_network_data (sqlite3_context *context) {
733673 return netdata ;
734674}
735675
736- void cloudsync_network_init (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
737- DEBUG_FUNCTION ("cloudsync_network_init" );
738-
676+ static void cloudsync_network_init_internal (sqlite3_context * context , const char * address , const char * managedDatabaseId ) {
739677 #ifndef CLOUDSYNC_OMIT_CURL
740678 curl_global_init (CURL_GLOBAL_ALL );
741679 #endif
742-
743- // no real network operations here
744- // just setup the network_data struct
680+
745681 cloudsync_context * data = (cloudsync_context * )sqlite3_user_data (context );
746682 network_data * netdata = cloudsync_network_data (context );
747683 if (!netdata ) goto abort_memory ;
748-
684+
749685 // init context
750686 uint8_t * site_id = (uint8_t * )cloudsync_context_init (data );
751687 if (!site_id ) goto abort_siteid ;
752-
688+
753689 // save site_id string representation: 01957493c6c07e14803727e969f1d2cc
754690 cloudsync_uuid_v7_stringify (site_id , netdata -> site_id , false);
755-
756- // connection string is a JSON object:
757- // {"address":"https://UUID.sqlite.cloud:443","database":"chinook.sqlite","projectID":"abc123","organizationID":"org456","apikey":"KEY"}
758- // apikey/token are optional and can be set later via cloudsync_network_set_token/cloudsync_network_set_apikey
759-
760- const char * connection_param = (const char * )sqlite3_value_text (argv [0 ]);
761-
691+
762692 // compute endpoints
763- if ( network_compute_endpoints ( context , netdata , connection_param ) == false) {
764- // error message/code already set inside network_compute_endpoints
693+ // authentication can be set later via cloudsync_network_set_token/cloudsync_network_set_apikey
694+ if ( network_compute_endpoints_with_address ( context , netdata , address , managedDatabaseId ) == false) {
765695 goto abort_cleanup ;
766696 }
767-
697+
768698 cloudsync_set_auxdata (data , netdata );
769699 sqlite3_result_int (context , SQLITE_OK );
770700 return ;
771-
701+
772702abort_memory :
773703 sqlite3_result_error (context , "Unable to allocate memory in cloudsync_network_init." , -1 );
774704 sqlite3_result_error_code (context , SQLITE_NOMEM );
775705 goto abort_cleanup ;
776-
706+
777707abort_siteid :
778708 sqlite3_result_error (context , "Unable to compute/retrieve site_id." , -1 );
779709 sqlite3_result_error_code (context , SQLITE_MISUSE );
780710 goto abort_cleanup ;
781-
711+
782712abort_cleanup :
783713 cloudsync_set_auxdata (data , NULL );
784714 network_data_free (netdata );
785715}
786716
717+ void cloudsync_network_init (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
718+ DEBUG_FUNCTION ("cloudsync_network_init" );
719+ const char * managedDatabaseId = (const char * )sqlite3_value_text (argv [0 ]);
720+ cloudsync_network_init_internal (context , CLOUDSYNC_DEFAULT_ADDRESS , managedDatabaseId );
721+ }
722+
723+ void cloudsync_network_init_custom (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
724+ DEBUG_FUNCTION ("cloudsync_network_init_custom" );
725+ const char * address = (const char * )sqlite3_value_text (argv [0 ]);
726+ const char * managedDatabaseId = (const char * )sqlite3_value_text (argv [1 ]);
727+ cloudsync_network_init_internal (context , address , managedDatabaseId );
728+ }
729+
787730void cloudsync_network_cleanup_internal (sqlite3_context * context ) {
788731 cloudsync_context * data = (cloudsync_context * )sqlite3_user_data (context );
789732 network_data * netdata = cloudsync_network_data (context );
@@ -828,7 +771,7 @@ void cloudsync_network_set_token (sqlite3_context *context, int argc, sqlite3_va
828771
829772void cloudsync_network_set_apikey (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
830773 DEBUG_FUNCTION ("cloudsync_network_set_apikey" );
831-
774+
832775 const char * value = (const char * )sqlite3_value_text (argv [0 ]);
833776 bool result = cloudsync_network_set_authentication_token (context , value , false);
834777 (result ) ? sqlite3_result_int (context , SQLITE_OK ) : sqlite3_result_error_code (context , SQLITE_NOMEM );
@@ -1258,6 +1201,9 @@ int cloudsync_network_register (sqlite3 *db, char **pzErrMsg, void *ctx) {
12581201 rc = sqlite3_create_function (db , "cloudsync_network_init" , 1 , DEFAULT_FLAGS , ctx , cloudsync_network_init , NULL , NULL );
12591202 if (rc != SQLITE_OK ) goto cleanup ;
12601203
1204+ rc = sqlite3_create_function (db , "cloudsync_network_init_custom" , 2 , DEFAULT_FLAGS , ctx , cloudsync_network_init_custom , NULL , NULL );
1205+ if (rc != SQLITE_OK ) return rc ;
1206+
12611207 rc = sqlite3_create_function (db , "cloudsync_network_cleanup" , 0 , DEFAULT_FLAGS , ctx , cloudsync_network_cleanup , NULL , NULL );
12621208 if (rc != SQLITE_OK ) return rc ;
12631209
0 commit comments