diff httpauth.c @ 5879:61062082488b libavformat

Split out http authentication handling into a separate file This prepares for adding support for more authentication methods
author mstorsjo
date Wed, 24 Mar 2010 22:32:05 +0000
parents
children a1a309c4a751
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/httpauth.c	Wed Mar 24 22:32:05 2010 +0000
@@ -0,0 +1,132 @@
+/*
+ * HTTP authentication
+ * Copyright (c) 2010 Martin Storsjo
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "httpauth.h"
+#include "libavutil/base64.h"
+#include "libavutil/avstring.h"
+#include "avformat.h"
+#include <ctype.h>
+
+static void parse_key_value(const char *params,
+                            void (*callback_get_buf)(HTTPAuthState *state,
+                            const char *key, int key_len,
+                            char **dest, int *dest_len), HTTPAuthState *state)
+{
+    const char *ptr = params;
+
+    /* Parse key=value pairs. */
+    for (;;) {
+        const char *key;
+        char *dest = NULL, *dest_end;
+        int key_len, dest_len = 0;
+
+        /* Skip whitespace and potential commas. */
+        while (*ptr && (isspace(*ptr) || *ptr == ','))
+            ptr++;
+        if (!*ptr)
+            break;
+
+        key = ptr;
+
+        if (!(ptr = strchr(key, '=')))
+            break;
+        ptr++;
+        key_len = ptr - key;
+
+        callback_get_buf(state, key, key_len, &dest, &dest_len);
+        dest_end = dest + dest_len - 1;
+
+        if (*ptr == '\"') {
+            ptr++;
+            while (*ptr && *ptr != '\"') {
+                if (*ptr == '\\') {
+                    if (!ptr[1])
+                        break;
+                    if (dest && dest < dest_end)
+                        *dest++ = ptr[1];
+                    ptr += 2;
+                } else {
+                    if (dest && dest < dest_end)
+                        *dest++ = *ptr;
+                    ptr++;
+                }
+            }
+            if (*ptr == '\"')
+                ptr++;
+        } else {
+            for (; *ptr && !(isspace(*ptr) || *ptr == ','); ptr++)
+                if (dest && dest < dest_end)
+                    *dest++ = *ptr;
+        }
+        if (dest)
+            *dest = 0;
+    }
+}
+
+static void handle_basic_params(HTTPAuthState *state, const char *key,
+                                int key_len, char **dest, int *dest_len)
+{
+    if (!strncmp(key, "realm=", key_len)) {
+        *dest     =        state->realm;
+        *dest_len = sizeof(state->realm);
+    }
+}
+
+void ff_http_auth_handle_header(HTTPAuthState *state, const char *key,
+                                const char *value)
+{
+    if (!state)
+        return;
+
+    if (!strcmp(key, "WWW-Authenticate")) {
+        const char *p;
+        if (av_stristart(value, "Basic ", &p) &&
+            state->auth_type <= HTTP_AUTH_BASIC) {
+            state->auth_type = HTTP_AUTH_BASIC;
+            state->realm[0] = 0;
+            parse_key_value(p, handle_basic_params, state);
+        }
+    }
+}
+
+char *ff_http_auth_create_response(HTTPAuthState *state, const char *auth,
+                                   const char *path, const char *method)
+{
+    char *authstr = NULL;
+
+    if (!auth || !strchr(auth, ':'))
+        return NULL;
+
+    if (state->auth_type == HTTP_AUTH_BASIC) {
+        int auth_b64_len = (strlen(auth) + 2) / 3 * 4 + 1;
+        int len = auth_b64_len + 30;
+        char *ptr;
+        authstr = av_malloc(len);
+        if (!authstr)
+            return NULL;
+        snprintf(authstr, len, "Authorization: Basic ");
+        ptr = authstr + strlen(authstr);
+        av_base64_encode(ptr, auth_b64_len, auth, strlen(auth));
+        av_strlcat(ptr, "\r\n", len);
+    }
+    return authstr;
+}
+