]> diplodocus.org Git - nmh/blobdiff - sbr/oauth.c
Don't need to cast to `char *' for free(3) these days.
[nmh] / sbr / oauth.c
old mode 100644 (file)
new mode 100755 (executable)
index 85fe714..87ee779
 
 #define JSON_TYPE "application/json"
 
-/* We pretend access tokens expire 30 seconds earlier than they actually do to
+/* We pretend access tokens expire 60 seconds earlier than they actually do to
  * allow for separate processes to use and refresh access tokens.  The process
  * that uses the access token (post) has an error if the token is expired; the
  * process that refreshes the access token (send) must have already refreshed if
  * the expiration is close.
  *
- * 30s is arbitrary, and hopefully is enough to allow for clock skew.
+ * 60s is arbitrary, and hopefully is enough to allow for clock skew.
  * Currently only Gmail supports XOAUTH2, and seems to always use a token
  * life-time of 3600s, but that is not guaranteed.  It is possible for Gmail to
  * issue an access token with a life-time so short that even after send
@@ -44,7 +44,7 @@
  * (not counting header and not null-terminated) */
 #define RESPONSE_BODY_MAX 8192
 
-/* Maxium size for URLs and URI-encoded query strings, null-terminated.
+/* Maximum size for URLs and URI-encoded query strings, null-terminated.
  *
  * Actual maximum we need is based on the size of tokens (limited by
  * RESPONSE_BODY_MAX), code user copies from a web page (arbitrarily large), and
@@ -142,7 +142,7 @@ mh_oauth_do_xoauth(const char *user, const char *svc, unsigned char **oauth_res,
 
     if (log != NULL) mh_oauth_log_to(stderr, ctx);
 
-    fn = getcpy(mh_oauth_cred_fn(svc));
+    fn = mh_xstrdup(mh_oauth_cred_fn(svc));
     fp = lkfopendata(fn, "r+", &failed_to_lock);
     if (fp == NULL) {
         if (errno == ENOENT) {
@@ -182,7 +182,7 @@ mh_oauth_do_xoauth(const char *user, const char *svc, unsigned char **oauth_res,
     free(fn);
 
     /* XXX writeBase64raw modifies the source buffer!  make a copy */
-    client_res = getcpy(mh_oauth_sasl_client_response(oauth_res_len, user,
+    client_res = mh_xstrdup(mh_oauth_sasl_client_response(oauth_res_len, user,
                                                       cred));
     mh_oauth_cred_free(cred);
     mh_oauth_free(ctx);
@@ -242,21 +242,16 @@ static char *
 make_user_agent()
 {
     const char *curl = curl_version_info(CURLVERSION_NOW)->version;
-    char *s = mh_xmalloc(strlen(user_agent)
-                         + 1
-                         + sizeof "libcurl"
-                         + 1
-                         + strlen(curl)
-                         + 1);
-    sprintf(s, "%s libcurl/%s", user_agent, curl);
-    return s;
+    return concat(user_agent, " libcurl/", curl, NULL);
 }
 
 boolean
 mh_oauth_new(mh_oauth_ctx **result, const char *svc_name)
 {
-    mh_oauth_ctx *ctx = *result = mh_xmalloc(sizeof *ctx);
+    mh_oauth_ctx *ctx;
 
+    NEW(ctx);
+    *result = ctx;
     ctx->curl = NULL;
 
     ctx->log = NULL;
@@ -328,7 +323,6 @@ mh_oauth_get_err_code(const mh_oauth_ctx *ctx)
 const char *
 mh_oauth_get_err_string(mh_oauth_ctx *ctx)
 {
-    char *result;
     const char *base;
 
     free(ctx->err_formatted);
@@ -372,12 +366,11 @@ mh_oauth_get_err_string(mh_oauth_ctx *ctx)
         base = "unknown error";
     }
     if (ctx->err_details == NULL) {
-        return ctx->err_formatted = getcpy(base);
+        return ctx->err_formatted = mh_xstrdup(base);
     }
-    /* length of the two strings plus ": " and '\0' */
-    result = mh_xmalloc(strlen(base) + strlen(ctx->err_details) + 3);
-    sprintf(result, "%s: %s", base, ctx->err_details);
-    return ctx->err_formatted = result;
+
+    ctx->err_formatted = concat(base, ": ", ctx->err_details, NULL);
+    return ctx->err_formatted;
 }
 
 const char *
@@ -507,7 +500,7 @@ mh_oauth_authorize(const char *code, mh_oauth_ctx *ctx)
         return NULL;
     }
 
-    result = mh_xmalloc(sizeof *result);
+    NEW(result);
     result->ctx = ctx;
     result->access_token = result->refresh_token = NULL;
 
@@ -622,7 +615,8 @@ load_creds(struct user_creds **result, FILE *fp, mh_oauth_ctx *ctx)
     int state;
     m_getfld_state_t getfld_ctx = 0;
 
-    struct user_creds *user_creds = mh_xmalloc(sizeof *user_creds);
+    struct user_creds *user_creds;
+    NEW(user_creds);
     user_creds->alloc = 4;
     user_creds->len = 0;
     user_creds->creds = mh_xmalloc(user_creds->alloc * sizeof *user_creds->creds);
@@ -814,17 +808,13 @@ const char *
 mh_oauth_sasl_client_response(size_t *res_len,
                               const char *user, const mh_oauth_cred *cred)
 {
-    size_t len = sizeof "user=" - 1
-        + strlen(user)
-        + sizeof "\1auth=Bearer " - 1
-        + strlen(cred->access_token)
-        + sizeof "\1\1" - 1;
-    free(cred->ctx->sasl_client_res);
-    cred->ctx->sasl_client_res = mh_xmalloc(len + 1);
-    *res_len = len;
-    sprintf(cred->ctx->sasl_client_res, "user=%s\1auth=Bearer %s\1\1",
-            user, cred->access_token);
-    return cred->ctx->sasl_client_res;
+    char **p;
+
+    p = &cred->ctx->sasl_client_res;
+    free(*p);
+    *p = concat("user=", user, "\1auth=Bearer ", cred->access_token, "\1\1", NULL);
+    *res_len = strlen(*p);
+    return *p;
 }
 
 /*******************************************************************************
@@ -850,7 +840,10 @@ make_query_url(char *s, size_t size, CURL *curl, const char *base_url, ...)
         len = 0;
         prefix = "";
     } else {
-        len = sprintf(s, "%s", base_url);
+        len = strlen(base_url);
+        if (len > size - 1) /* Less one for NUL. */
+            return FALSE;
+        strcpy(s, base_url);
         prefix = "?";
     }
 
@@ -904,7 +897,7 @@ debug_callback(const CURL *handle, curl_infotype type, const char *data,
     }
     fwrite(data, 1, size, fp);
     if (data[size - 1] != '\n') {
-        fputs("\n", fp);
+        putc('\n', fp);
     }
     fflush(fp);
     return 0;
@@ -956,6 +949,14 @@ post(struct curl_ctx *ctx, const char *url, const char *req_body)
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
     curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx);
 
+    if (strncmp(url, "http://127.0.0.1:", 17) == 0) {
+        /* Hack:  on Cygwin, curl doesn't fail to connect with ECONNREFUSED.
+           Instead, it waits to timeout.  So set a really short timeout, but
+           just on localhost (for convenience of the user, and the test
+           suite). */
+        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L);
+    }
+
     status = curl_easy_perform(curl);
     /* first check for error from callback */
     if (ctx->too_big) {