static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream) { auth_client *auth_user = stream; unsigned bytes = size * nmemb; client_t *client = auth_user->client; auth_thread_data *atd = auth_user->thread_data; char *header = (char *)ptr, *header_data; if (bytes <= 1 || client == NULL) return bytes; do { auth_t *auth = auth_user->auth; auth_url *url = auth->state; int retcode = 0, header_datalen; /* replace the EOL with a nul char, libcurl may not provide a nul */ header [bytes-2] = '\0'; if (sscanf (ptr, "HTTP%*c%*u.%*u %3d %*c", &retcode) == 1) { if (retcode == 403) { char *p = strchr (ptr, ' ') + 1; snprintf (atd->errormsg, sizeof(atd->errormsg), "%s", p); p = strchr (atd->errormsg, '\r'); if (p) *p='\0'; } else if ((auth->flags & AUTH_SKIP_IF_SLOW) && retcode >= 400 && retcode < 600) { snprintf (atd->errormsg, sizeof(atd->errormsg), "auth on %s disabled, response was \'%.200s...\'", auth->mount, header); url->stop_req_until = time (NULL) + url->stop_req_duration; /* prevent further attempts for a while */ client->flags |= CLIENT_AUTHENTICATED; return bytes; } } header_data = strchr (header, ':'); if (header_data == NULL) return bytes; header_data++; header_data += strspn (header_data, " \t"); // find non-space start header_datalen = strcspn (header_data, "\r\n"); // find length if (strncasecmp (header, url->auth_header, url->auth_header_len) == 0) { client->flags |= CLIENT_AUTHENTICATED; if (header_data) { if (strstr (header_data, "withintro")) client->flags |= CLIENT_HAS_INTRO_CONTENT; if (strstr (header_data, "hijack")) client->flags |= CLIENT_HIJACKER; if (strstr (header_data, "0")) { WARN0 ("auth header returned with 0 value"); client->flags &= ~CLIENT_AUTHENTICATED; } } break; } if (strncasecmp (header, url->timelimit_header, url->timelimit_header_len) == 0) { unsigned int limit = 60; sscanf (header_data, "%u\r\n", &limit); client->connection.discon.time = time(NULL) + limit; break; } if (strncasecmp (header, "icecast-slave:", 14) == 0) { client->flags |= CLIENT_IS_SLAVE; break; } if (strncasecmp (header, "icecast-auth-message:", 21) == 0) { snprintf (atd->errormsg, sizeof (atd->errormsg), "%.*s", header_datalen, header_data); break; } if (strncasecmp (header, "ice-username:"******"%s", header_data); free (client->username); client->username = name; } break; } if (strncasecmp (header, "Location:", 9) == 0) { free (atd->location); atd->location = malloc (header_datalen+1); if (atd->location) snprintf (atd->location, header_datalen+1, "%s", header_data); break; } if (strncasecmp (header, "Mountpoint:", 11) == 0) { char *mount = malloc (header_datalen+1); if (mount) { snprintf (mount, header_datalen+1, "%s", header_data); free (auth_user->mount); auth_user->mount = mount; } break; } if (strncasecmp (header, "content-type:", 13) == 0) { format_type_t type = format_get_type (header_data); if (client->refbuf && (type == FORMAT_TYPE_AAC || type == FORMAT_TYPE_MPEG)) { struct build_intro_contents *x = (void*)client->refbuf->data; x->type = type; mpeg_setup (&x->sync, client->connection.ip); } break; } } while (0); return (int)bytes; }
static size_t handle_returned_header (void *ptr, size_t size, size_t nmemb, void *stream) { auth_client *auth_user = stream; unsigned bytes = size * nmemb; client_t *client = auth_user->client; auth_thread_data *atd = auth_user->thread_data; if (bytes <= 1) // we should have the EOL at least return bytes; if (client) { auth_t *auth = auth_user->auth; auth_url *url = auth->state; int retcode = 0; char *p = ptr; /* replace the EOL with a nul char, libcurl may not provide a nul */ p[bytes-2] = '\0'; if (sscanf (ptr, "HTTP%*c%*u.%*u %3d %*c", &retcode) == 1) { if (retcode == 403) { char *p = strchr (ptr, ' ') + 1; snprintf (atd->errormsg, sizeof(atd->errormsg), "%s", p); p = strchr (atd->errormsg, '\r'); if (p) *p='\0'; } } if (strncasecmp (ptr, url->auth_header, url->auth_header_len) == 0) { client->flags |= CLIENT_AUTHENTICATED; p = strchr (ptr, ':'); if (p) { ++p; if (strstr (p, "withintro")) client->flags |= CLIENT_HAS_INTRO_CONTENT; if (strstr (p, "hijack")) client->flags |= CLIENT_HIJACKER; if (strstr (p, "0")) { WARN0 ("auth header returned with 0 value"); client->flags &= ~CLIENT_AUTHENTICATED; } } } if (strncasecmp (ptr, url->timelimit_header, url->timelimit_header_len) == 0) { unsigned int limit = 0; sscanf ((char *)ptr+url->timelimit_header_len, "%u\r\n", &limit); client->connection.discon_time = time(NULL) + limit; } if (strncasecmp (ptr, "icecast-slave: 1", 16) == 0) client->flags |= CLIENT_IS_SLAVE; if (strncasecmp (ptr, "icecast-auth-message: ", 22) == 0) { char *eol; snprintf (atd->errormsg, sizeof (atd->errormsg), "%s", (char*)ptr+22); eol = strchr (atd->errormsg, '\r'); if (eol == NULL) eol = strchr (atd->errormsg, '\n'); if (eol) *eol = '\0'; } if (strncasecmp (ptr, "ice-username: "******"\r\n"); char *name = malloc (len+1); if (name) { snprintf (name, len+1, "%s", (char *)ptr+14); free (client->username); client->username = name; } } if (strncasecmp (ptr, "Location: ", 10) == 0) { int len = strcspn ((char*)ptr+10, "\r\n"); free (atd->location); atd->location = malloc (len+1); snprintf (atd->location, len+1, "%s", (char *)ptr+10); } if (strncasecmp (ptr, "Mountpoint: ", 12) == 0) { int len = strcspn ((char*)ptr+12, "\r\n"); char *mount = malloc (len+1); if (mount) { snprintf (mount, len+1, "%s", (char *)ptr+12); free (auth_user->mount); auth_user->mount = mount; } } if (strncasecmp (ptr, "content-type: ", 14) == 0) { format_type_t type = format_get_type ((char*)ptr+14); if (client->refbuf && (type == FORMAT_TYPE_AAC || type == FORMAT_TYPE_MPEG)) { struct build_intro_contents *x = (void*)client->refbuf->data; x->type = type; mpeg_setup (&x->sync, client->connection.ip); } } } return (int)bytes; }