void _set_curl_options(SG_context* pCtx, CURL* pCurl) { char * szServerFiles = NULL; char * szVerifyCerts = NULL; SG_pathname *pServerFiles = NULL; CURLcode rc = CURLE_OK; #ifdef WINDOWS SG_bool bExists = SG_FALSE; SG_bool bVerifyCerts = SG_TRUE; #endif SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__VERIFY_SSL_CERTS, NULL, &szVerifyCerts, NULL) ); if (szVerifyCerts != NULL && (SG_strcmp__null(szVerifyCerts, "false") == 0 || SG_strcmp__null(szVerifyCerts, "FALSE") == 0)) { #ifdef WINDOWS bVerifyCerts = SG_FALSE; #endif rc = curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, SG_FALSE); } if (rc) SG_ERR_THROW(SG_ERR_LIBCURL(rc)); #ifdef WINDOWS if (bVerifyCerts) { SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__SERVER_FILES, NULL, &szServerFiles, NULL) ); if (szServerFiles) { SG_ERR_CHECK( SG_pathname__alloc__sz(pCtx, &pServerFiles, szServerFiles) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pServerFiles, "ssl") ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pServerFiles, "curl-ca-bundle.crt") ); SG_ERR_CHECK( SG_fsobj__exists__pathname(pCtx, pServerFiles, &bExists, NULL, NULL) ); } if (bExists) { rc = curl_easy_setopt(pCurl, CURLOPT_CAINFO, SG_pathname__sz(pServerFiles)); if (rc) SG_ERR_THROW(SG_ERR_LIBCURL(rc)); } else { if (pServerFiles) SG_ERR_CHECK( SG_log__report_warning(pCtx, "Could not find root certificate file. Looked for it at: %s. SSL connections will not work.", SG_pathname__sz(pServerFiles)) ); else SG_ERR_CHECK( SG_log__report_warning(pCtx, "Could not find root certificate file: no server/files path is configured. SSL connections will not work.") ); } } #endif fail: SG_PATHNAME_NULLFREE(pCtx, pServerFiles); SG_NULLFREE(pCtx, szServerFiles); SG_NULLFREE(pCtx, szVerifyCerts); }
static void _sg_jscore_getpaths(SG_context *pCtx) { char * szServerFiles = NULL; if (gpJSCoreGlobalState->pPathToDispatchDotJS) return; // Figure out and store relavant paths... SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__SERVER_FILES, NULL, &szServerFiles, NULL) ); if (szServerFiles) { SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &gpJSCoreGlobalState->pPathToDispatchDotJS, szServerFiles) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToDispatchDotJS, "dispatch.js") ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &gpJSCoreGlobalState->pPathToCore, szServerFiles) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToCore, "core") ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &gpJSCoreGlobalState->pPathToModules, szServerFiles) ); SG_ERR_CHECK( SG_pathname__append__from_sz(pCtx, gpJSCoreGlobalState->pPathToModules, "modules") ); } fail: SG_NULLFREE(pCtx, szServerFiles); }
void SG_user__get_email_for_repo(SG_context * pCtx, SG_repo* pRepo, const char ** ppsz_email) { char * psz_admin_id = NULL; char * psz_userid = NULL; const char * psz_email_temp = NULL; SG_string * pstr_path = NULL; SG_vhash * pvh_userhash = NULL; if (pRepo) { SG_ERR_CHECK( SG_repo__get_admin_id(pCtx, pRepo, &psz_admin_id) ); // we store this userid under the admin scope of the repo we were given SG_ERR_CHECK( SG_string__alloc__format(pCtx, &pstr_path, "%s/%s/%s", SG_LOCALSETTING__SCOPE__ADMIN, psz_admin_id, SG_LOCALSETTING__USERID ) ); SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_string__sz(pstr_path), pRepo, &psz_userid, NULL) ); if (psz_userid == NULL || *psz_userid == 0) SG_ERR_THROW(SG_ERR_USER_NOT_FOUND); SG_ERR_CHECK( SG_user__lookup_by_userid(pCtx, pRepo, psz_userid, &pvh_userhash) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pvh_userhash, "email", &psz_email_temp) ); SG_ERR_CHECK( SG_STRDUP(pCtx, psz_email_temp, (char**)ppsz_email) ); } fail: SG_VHASH_NULLFREE(pCtx, pvh_userhash); SG_NULLFREE(pCtx, psz_admin_id); SG_NULLFREE(pCtx, psz_userid); SG_STRING_NULLFREE(pCtx, pstr_path); }
/** * Find the appropriate external tool to let the user perform a TEXT MERGE * on a file. * * TODO 2010/07/13 For now, this is hard-coded to use DiffMerge. * TODO Later we want to allow them to have multiple * TODO tools configured and/or to use the file suffix * TODO and so on. */ static void _resolve__external_tool__lookup(SG_context * pCtx, struct _resolve_data * pData, const char * pszGid, const SG_vhash * pvhIssue, SG_string * pStrRepoPath, _resolve__external_tool ** ppET) { _resolve__external_tool * pET = NULL; SG_repo * pRepo; SG_UNUSED( pszGid ); SG_UNUSED( pvhIssue ); SG_ERR_CHECK( SG_pendingtree__get_repo(pCtx, pData->pPendingTree, &pRepo) ); SG_ERR_CHECK( SG_alloc1(pCtx, pET) ); // TODO 2010/07/13 Use localsettings to determine WHICH external tool we should use. // TODO (This could be based upon suffixes and/or whatever.) // TODO Then -- for THAT tool -- lookup the program executable path and // TODO the argument list. // TODO Substitute the given pathnames into the argument list. // TODO // TODO For now, we just hard-code DiffMerge. SG_ERR_CHECK( SG_strdup(pCtx, "DiffMerge", &pET->pszName) ); SG_localsettings__get__sz(pCtx, "merge/diffmerge/program", pRepo, &pET->pszExe, NULL); if (SG_context__has_err(pCtx) || (!pET->pszExe) || (!*pET->pszExe)) { SG_context__err_reset(pCtx); SG_ERR_THROW2( SG_ERR_NO_MERGE_TOOL_CONFIGURED, (pCtx, "'%s' Use 'vv localsetting set merge/diffmerge/program' and retry -or- manually merge content and then use 'vv resolve --mark'.", SG_string__sz(pStrRepoPath)) ); } // TODO 2010/07/13 Get argvec. *ppET = pET; return; fail: _RESOLVE__EXTERNAL_TOOL__NULLFREE(pCtx, pET); }
void MyFn(create_repo)(SG_context * pCtx, SG_repo ** ppRepo) { // caller must free returned value. SG_repo * pRepo; SG_pathname * pPathnameRepoDir = NULL; SG_vhash* pvhPartialDescriptor = NULL; char buf_repo_id[SG_GID_BUFFER_LENGTH]; char buf_admin_id[SG_GID_BUFFER_LENGTH]; char* pszRepoImpl = NULL; VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_repo_id, sizeof(buf_repo_id)) ); VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_admin_id, sizeof(buf_admin_id)) ); VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC(pCtx, &pPathnameRepoDir) ); VERIFY_ERR_CHECK( SG_pathname__set__from_cwd(pCtx, pPathnameRepoDir) ); VERIFY_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhPartialDescriptor) ); VERIFY_ERR_CHECK_DISCARD( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__NEWREPO_DRIVER, NULL, &pszRepoImpl, NULL) ); VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_KEY__STORAGE, pszRepoImpl) ); VERIFY_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_FSLOCAL__PATH_PARENT_DIR, SG_pathname__sz(pPathnameRepoDir)) ); VERIFY_ERR_CHECK( SG_repo__create_repo_instance(pCtx,pvhPartialDescriptor,SG_TRUE,NULL,buf_repo_id,buf_admin_id,&pRepo) ); SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); { const SG_vhash * pvhRepoDescriptor = NULL; VERIFY_ERR_CHECK( SG_repo__get_descriptor(pCtx, pRepo,&pvhRepoDescriptor) ); //INFOP("open_repo",("Repo is [%s]",SG_string__sz(pstrRepoDescriptor))); } *ppRepo = pRepo; fail: SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); SG_PATHNAME_NULLFREE(pCtx, pPathnameRepoDir); SG_NULLFREE(pCtx, pszRepoImpl); }
void MyFn(create_repo)(SG_context * pCtx, SG_repo** ppRepo) { SG_repo* pRepo = NULL; SG_pathname* pPath_repo = NULL; char buf_repo_id[SG_GID_BUFFER_LENGTH]; char buf_admin_id[SG_GID_BUFFER_LENGTH]; SG_vhash* pvhPartialDescriptor = NULL; char* pszRepoImpl = NULL; VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_repo_id, sizeof(buf_repo_id)) ); VERIFY_ERR_CHECK( SG_gid__generate(pCtx, buf_admin_id, sizeof(buf_admin_id)) ); /* Get our paths fixed up */ VERIFY_ERR_CHECK( SG_PATHNAME__ALLOC(pCtx, &pPath_repo) ); VERIFY_ERR_CHECK( SG_pathname__set__from_cwd(pCtx, pPath_repo) ); VERIFY_ERR_CHECK( SG_pathname__append__from_sz(pCtx, pPath_repo, "repo") ); SG_fsobj__mkdir__pathname(pCtx, pPath_repo); SG_context__err_reset(pCtx); // Create the repo VERIFY_ERR_CHECK( SG_VHASH__ALLOC(pCtx, &pvhPartialDescriptor) ); VERIFY_ERR_CHECK_DISCARD( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__NEWREPO_DRIVER, NULL, &pszRepoImpl, NULL) ); if (pszRepoImpl) { VERIFY_ERR_CHECK_DISCARD( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_KEY__STORAGE, pszRepoImpl) ); } VERIFY_ERR_CHECK( SG_vhash__add__string__sz(pCtx, pvhPartialDescriptor, SG_RIDESC_FSLOCAL__PATH_PARENT_DIR, SG_pathname__sz(pPath_repo)) ); VERIFY_ERR_CHECK( SG_repo__create_repo_instance(pCtx,NULL,pvhPartialDescriptor,SG_TRUE,NULL,buf_repo_id,buf_admin_id,&pRepo) ); *ppRepo = pRepo; // Fall through to common cleanup fail: SG_VHASH_NULLFREE(pCtx, pvhPartialDescriptor); SG_PATHNAME_NULLFREE(pCtx, pPath_repo); SG_NULLFREE(pCtx, pszRepoImpl); }
static void _remote_clone_allowed(SG_context* pCtx) { char* pszSetting = NULL; SG_bool bAllowed = SG_TRUE; SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__SERVER_CLONE_ALLOWED, NULL, &pszSetting, NULL); if(!SG_context__has_err(pCtx) && pszSetting != NULL) bAllowed = (strcmp(pszSetting, "true")==0); if(SG_context__has_err(pCtx)) { SG_log__report_error__current_error(pCtx); SG_context__err_reset(pCtx); } if (!bAllowed) SG_ERR_THROW(SG_ERR_SERVER_DISALLOWED_REPO_CREATE_OR_DELETE); /* fall through */ fail: SG_NULLFREE(pCtx, pszSetting); }
/** * Let the UI dispatch methods know where to find their template files. */ void _sgui_set_templatePath(SG_context * pCtx) { SG_pathname *collateralRoot = NULL; SG_pathname * templatePath = NULL; char* psz = NULL; SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__SSI_DIR, NULL, &psz, NULL) ); SG_ERR_CHECK( SG_pathname__alloc__sz(pCtx, &collateralRoot, psz) ); SG_ERR_CHECK( SG_PATHNAME__ALLOC__PATHNAME_SZ(pCtx, &templatePath, collateralRoot, "templates") ); SG_NULLFREE(pCtx, psz); SG_PATHNAME_NULLFREE(pCtx, collateralRoot); _sg_uridispatch__templatePath = templatePath; return; fail: SG_NULLFREE(pCtx, psz); SG_PATHNAME_NULLFREE(pCtx, templatePath); SG_PATHNAME_NULLFREE(pCtx, collateralRoot); }
void GetProfileSettings( SG_context* pCtx, const char* szProfile, char** ppszDest, char** ppszSrc, SG_int64* plSyncIntervalMinutes, LPWSTR* ppwszErr) { static const LPWSTR ERR_NO_DEST = L"No destination repository is configured."; static const LPWSTR ERR_NO_SRC = L"No source repository is configured."; char* pszDest = NULL; char* pszSrc = NULL; SG_variant* pvMinutes = NULL; SG_string* pstrConfigPath = NULL; SG_uint64 lMinutes; LPWSTR pwszErr = NULL; /* It's kind of icky, but we copy these error strings so the balloon code that displays them doesn't have to be very smart and can always free the message string. (Generic unhandled errors aren't constant, so it has to free those.) I'm not sure making the balloon code more complexso this can be simpler is a net win, so I'm leaving this be. But it is icky. */ SG_ERR_CHECK( SG_string__alloc__format(pCtx, &pstrConfigPath, "%s/%s/%s", CONFIG_ROOT, szProfile, CONFIG_DEST) ); SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_string__sz(pstrConfigPath), NULL, &pszDest, NULL) ); SG_ERR_CHECK( SG_string__clear(pCtx, pstrConfigPath) ); if (!pszDest || !pszDest[0]) { size_t len_in_chars = 0; if (FAILED( StringCchLength(ERR_NO_DEST, STRSAFE_MAX_CCH, &len_in_chars) )) SG_ERR_THROW(SG_ERR_GETLASTERROR(GetLastError())); pwszErr = (LPWSTR)malloc(sizeof(wchar_t) * (len_in_chars + 1)); if (FAILED( StringCchCopy(pwszErr, len_in_chars + 1, ERR_NO_DEST) )) SG_ERR_THROW(SG_ERR_GETLASTERROR(GetLastError())); } SG_ERR_CHECK( SG_string__append__format(pCtx, pstrConfigPath, "%s/%s/%s", CONFIG_ROOT, szProfile, CONFIG_SRC) ); SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_string__sz(pstrConfigPath), NULL, &pszSrc, NULL) ); SG_ERR_CHECK( SG_string__clear(pCtx, pstrConfigPath) ); if (!pwszErr) { if (!pszSrc || !pszSrc[0]) { size_t len_in_chars = 0; if (FAILED( StringCchLength(ERR_NO_SRC, STRSAFE_MAX_CCH, &len_in_chars) )) SG_ERR_THROW(SG_ERR_GETLASTERROR(GetLastError())); pwszErr = (LPWSTR)malloc(sizeof(wchar_t) * (len_in_chars + 1)); if (FAILED( StringCchCopy(pwszErr, len_in_chars + 1, ERR_NO_SRC) )) SG_ERR_THROW(SG_ERR_GETLASTERROR(GetLastError())); } } SG_ERR_CHECK( SG_string__append__format(pCtx, pstrConfigPath, "%s/%s/%s", CONFIG_ROOT, szProfile, CONFIG_INTERVAL) ); SG_ERR_CHECK( SG_localsettings__get__variant(pCtx, SG_string__sz(pstrConfigPath), NULL, &pvMinutes, NULL) ); if (!pvMinutes) lMinutes = DEFAULT_SYNC_EVERY_N_MINUTES; else SG_ERR_CHECK( SG_variant__get__uint64(pCtx, pvMinutes, &lMinutes) ); if (plSyncIntervalMinutes) *plSyncIntervalMinutes = lMinutes; SG_RETURN_AND_NULL(pszDest, ppszDest); SG_RETURN_AND_NULL(pszSrc, ppszSrc); SG_RETURN_AND_NULL(pwszErr, ppwszErr); /* common cleanup */ fail: SG_NULLFREE(pCtx, pszDest); SG_NULLFREE(pCtx, pszSrc); SG_VARIANT_NULLFREE(pCtx, pvMinutes); SG_STRING_NULLFREE(pCtx, pstrConfigPath); if (pwszErr) free(pwszErr); }
static void _set_up_logging( SG_context * pCtx, SG_log_console__data * pcLogStdData, SG_log_text__data * pcLogFileData, SG_log_text__writer__daily_path__data * pcLogFileWriterData) { // Code coppied from _my_main() in sg.c char * szLogLevel = NULL; char * szLogPath = NULL; SG_uint32 logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__ALL; // find the appropriate log path SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__LOG_PATH, NULL, &szLogPath, NULL) ); // get the configured log level SG_ERR_CHECK( SG_localsettings__get__sz(pCtx, SG_LOCALSETTING__LOG_LEVEL, NULL, &szLogLevel, NULL) ); // register the stdout logger SG_ERR_CHECK( SG_log_console__set_defaults(pCtx, pcLogStdData) ); SG_ERR_CHECK( SG_log_console__register(pCtx, pcLogStdData, NULL, SG_LOG__FLAG__HANDLER_TYPE__NORMAL) ); // register the file logger SG_ERR_CHECK( SG_log_text__set_defaults(pCtx, pcLogFileData) ); pcLogFileData->fWriter = SG_log_text__writer__daily_path; pcLogFileData->pWriterData = pcLogFileWriterData; pcLogFileData->szRegisterMessage = NULL; pcLogFileData->szUnregisterMessage = NULL; if (szLogLevel != NULL) { if (SG_stricmp(szLogLevel, "quiet") == 0) { logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__QUIET; pcLogFileData->bLogVerboseOperations = SG_FALSE; pcLogFileData->bLogVerboseValues = SG_FALSE; pcLogFileData->szVerboseFormat = NULL; pcLogFileData->szInfoFormat = NULL; } else if (SG_stricmp(szLogLevel, "normal") == 0) { logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__NORMAL; pcLogFileData->bLogVerboseOperations = SG_FALSE; pcLogFileData->bLogVerboseValues = SG_FALSE; pcLogFileData->szVerboseFormat = NULL; } else if (SG_stricmp(szLogLevel, "verbose") == 0) { logFileFlags = SG_LOG__FLAG__HANDLER_TYPE__ALL; pcLogFileData->szRegisterMessage = "---- vscript started logging ----"; pcLogFileData->szUnregisterMessage = "---- vscript stopped logging ----"; } } logFileFlags |= SG_LOG__FLAG__DETAILED_MESSAGES; SG_ERR_CHECK( SG_log_text__writer__daily_path__set_defaults(pCtx, pcLogFileWriterData) ); pcLogFileWriterData->bReopen = SG_FALSE; pcLogFileWriterData->ePermissions = 0666; if (szLogPath != NULL) SG_ERR_CHECK( SG_PATHNAME__ALLOC__SZ(pCtx, &pcLogFileWriterData->pBasePath, szLogPath) ); else SG_ERR_CHECK( SG_PATHNAME__ALLOC__LOG_DIRECTORY(pCtx, &pcLogFileWriterData->pBasePath) ); pcLogFileWriterData->szFilenameFormat = "vscript-%d-%02d-%02d.log"; SG_ERR_CHECK( SG_log_text__register(pCtx, pcLogFileData, NULL, logFileFlags) ); fail: SG_context__err_reset(pCtx); SG_NULLFREE(pCtx, szLogPath); SG_NULLFREE(pCtx, szLogLevel); }
void SG_cmd_util__get_username_for_repo( SG_context *pCtx, const char *szRepoName, char **ppUsername ) { SG_string * pUsername = NULL; SG_repo * pRepo = NULL; char * psz_username = NULL; SG_curl * pCurl = NULL; SG_string * pUri = NULL; SG_string * pResponse = NULL; SG_int32 responseStatusCode = 0; SG_vhash * pRepoInfo = NULL; char * psz_userid = NULL; SG_varray * pUsers = NULL; SG_NULLARGCHECK_RETURN(ppUsername); if(!szRepoName) { // Look up username based on 'whoami' of repo associated with cwd. SG_ERR_IGNORE( SG_cmd_util__get_repo_from_cwd(pCtx, &pRepo, NULL) ); if(pRepo) SG_ERR_IGNORE( SG_user__get_username_for_repo(pCtx, pRepo, &psz_username) ); SG_REPO_NULLFREE(pCtx, pRepo); } else if(SG_sz__starts_with(szRepoName, "http://") || SG_sz__starts_with(szRepoName, "https://")) { // Look up username based on 'whoami' of admin id of remote repo. SG_ERR_CHECK( SG_curl__alloc(pCtx, &pCurl) ); SG_ERR_CHECK( SG_STRING__ALLOC__SZ(pCtx, &pUri, szRepoName) ); SG_ERR_CHECK( SG_string__append__sz(pCtx, pUri, ".json") ); SG_ERR_CHECK( SG_curl__reset(pCtx, pCurl) ); SG_ERR_CHECK( SG_curl__setopt__sz(pCtx, pCurl, CURLOPT_URL, SG_string__sz(pUri)) ); SG_ERR_CHECK( SG_STRING__ALLOC(pCtx, &pResponse) ); SG_ERR_CHECK( SG_curl__set__write_string(pCtx, pCurl, pResponse) ); SG_ERR_CHECK( SG_curl__perform(pCtx, pCurl) ); SG_ERR_CHECK( SG_curl__getinfo__int32(pCtx, pCurl, CURLINFO_RESPONSE_CODE, &responseStatusCode) ); if(responseStatusCode==200) { const char * szAdminId = NULL; SG_ERR_CHECK( SG_VHASH__ALLOC__FROM_JSON__STRING(pCtx, &pRepoInfo, pResponse) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pRepoInfo, SG_SYNC_REPO_INFO_KEY__ADMIN_ID, &szAdminId) ); SG_ERR_CHECK( SG_string__clear(pCtx, pUri) ); SG_ERR_CHECK( SG_string__append__format(pCtx, pUri, "/admin/%s/whoami/userid", szAdminId) ); SG_ERR_IGNORE( SG_localsettings__get__sz(pCtx, SG_string__sz(pUri), NULL, &psz_userid, NULL) ); if(psz_userid) { // We now have the userid. Look up the username. SG_ERR_CHECK( SG_string__clear(pCtx, pUri) ); SG_ERR_CHECK( SG_string__append__format(pCtx, pUri, "%s/users.json", szRepoName) ); SG_ERR_CHECK( SG_curl__reset(pCtx, pCurl) ); SG_ERR_CHECK( SG_curl__setopt__sz(pCtx, pCurl, CURLOPT_URL, SG_string__sz(pUri)) ); SG_ERR_CHECK( SG_string__clear(pCtx, pResponse) ); SG_ERR_CHECK( SG_curl__set__write_string(pCtx, pCurl, pResponse) ); SG_ERR_CHECK( SG_curl__perform(pCtx, pCurl) ); SG_ERR_CHECK( SG_curl__getinfo__int32(pCtx, pCurl, CURLINFO_RESPONSE_CODE, &responseStatusCode) ); if(responseStatusCode==200) { SG_uint32 i, nUsers; SG_ERR_CHECK( SG_VARRAY__ALLOC__FROM_JSON__STRING(pCtx, &pUsers, pResponse) ); SG_ERR_CHECK( SG_varray__count(pCtx, pUsers, &nUsers) ); for(i=0; i<nUsers; ++i) { SG_vhash * pUser = NULL; const char * psz_recid = NULL; SG_ERR_CHECK( SG_varray__get__vhash(pCtx, pUsers, i, &pUser) ); SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pUser, "recid", &psz_recid) ); if(!strcmp(psz_recid, psz_userid)) { const char * psz_name = NULL; SG_ERR_CHECK( SG_vhash__get__sz(pCtx, pUser, "name", &psz_name) ); SG_ERR_CHECK( SG_STRDUP(pCtx, psz_name, &psz_username) ); break; } } SG_VARRAY_NULLFREE(pCtx, pUsers); } SG_NULLFREE(pCtx, psz_userid); } SG_VHASH_NULLFREE(pCtx, pRepoInfo); } SG_STRING_NULLFREE(pCtx, pResponse); SG_STRING_NULLFREE(pCtx, pUri); SG_CURL_NULLFREE(pCtx, pCurl); } else { // Look up username based on 'whoami' of repo provided. SG_ERR_CHECK( SG_REPO__OPEN_REPO_INSTANCE(pCtx, szRepoName, &pRepo) ); SG_ERR_IGNORE( SG_user__get_username_for_repo(pCtx, pRepo, &psz_username) ); SG_REPO_NULLFREE(pCtx, pRepo); } *ppUsername = psz_username; return; fail: SG_STRING_NULLFREE(pCtx, pUsername); SG_REPO_NULLFREE(pCtx, pRepo); SG_NULLFREE(pCtx, psz_username); SG_CURL_NULLFREE(pCtx, pCurl); SG_STRING_NULLFREE(pCtx, pUri); SG_STRING_NULLFREE(pCtx, pResponse); SG_VHASH_NULLFREE(pCtx, pRepoInfo); SG_NULLFREE(pCtx, psz_userid); SG_VARRAY_NULLFREE(pCtx, pUsers); }