⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************** *    http.c: for downloading via http (Hyper Text Transfer Protocol) *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * * This file is based on http implementation of mplayer. * mplayer's http implementation was very nice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * ***********************************************************************/ /* * Copyright notice of MPlayer project * which some part of msdl is based on. * (from MPlayer-1.0rc2/stream/http.c) *//*  * HTTP Helper * by Bertrand Baudet <bertrand_baudet@yahoo.com> * (C) 2001, MPlayer team. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "network.h"#include "http.h"const char http_useragent[] = "User-Agent: MSDL";/* * new_http_header : create new HTTP header */struct http_header_t *new_http_header(void){    struct http_header_t *hdr;    hdr = (struct http_header_t *)xmalloc(sizeof(struct http_header_t));    return hdr;}/* * free HTTP header */void free_http_header(struct http_header_t *h){    struct http_field_t *field, *prev;      if(h == NULL) return; /* http_hdr is not malloc()ed yet. */      if(h->protocol) free(h->protocol);    if(h->method) free(h->method);    if(h->uri) free(h->uri);    if(h->reason_phrase) free(h->reason_phrase);    if(h->field_search) free(h->field_search);    if(h->buffer) free(h->buffer);    field = h->first_field;    for(field = h->first_field; field ; ) {	if(field->field_name)	    free(field->field_name);	prev = field;	field = field->next;	free(prev);    }    free(h);}/* * returns first filed with 'field name'. * http_get_next_field will get next field with 'filed_name' */char *http_get_field(struct http_header_t *http_hdr, const char *field_name){    if(!http_hdr || !field_name) return NULL;      http_hdr->field_search_pos = http_hdr->first_field;    http_hdr->field_search = (char *)xrealloc(http_hdr->field_search,					      strlen(field_name) + 1);    /* copy field name first */        strcpy(http_hdr->field_search, field_name);    /* get first field value with this field_name. */    return http_get_next_field(http_hdr);}/* * return field string after "http_hdr->field_search". *        NULL if not found. */char *http_get_next_field(struct http_header_t *http_hdr){    char *ptr;    struct http_field_t *field;    if(!http_hdr) return NULL;    field = http_hdr->field_search_pos;      while(field) {	ptr = strstr(field->field_name,":");	if(ptr == NULL) return NULL; /* the header is not valid... */	if(!strncasecmp(field->field_name,http_hdr->field_search,			ptr - field->field_name)) { /* found field!!!! */	    ptr++; /* skip ':' */	    while(*ptr == ' ') ptr++; /* skip %20 */	    http_hdr->field_search_pos = field->next; /* points to next field */	    return ptr; /* return the string without filed name!! */	}	field = field->next;    }    return NULL; /* NOT FOUND */}/* * http_set_field : make new field and attach it to last_field->next. */void http_set_field(struct http_header_t *http_hdr, const char *field_name){    struct http_field_t *new_field;      if(http_hdr == NULL || field_name == NULL) return;      new_field = xmalloc(sizeof(struct http_field_t));    new_field->next = NULL;    new_field->field_name = xmalloc(strlen(field_name) + 1);    strcpy(new_field->field_name, field_name);      if(http_hdr->last_field == NULL) {	http_hdr->first_field = new_field; /* this was first filed!! */    }    else {	http_hdr->last_field->next = new_field; /* attach to last    */    }    http_hdr->last_field = new_field;    http_hdr->field_nb++;}/* * send 'http_hdr' to network. it has to be built by build_request funcs *                return value:  what xsend returned */int http_send_header(struct stream_t *stream,		     struct http_header_t *http_hdr){    int ret;      /* dbg */    display(MSDL_DBG,"SEND http header ------------>\n"	    "%s\n--(%d bytes)---------------<\n",	    http_hdr->buffer,(int)http_hdr->buffer_len);      ret = xsend(stream->netsock->sock,http_hdr->buffer,http_hdr->buffer_len);    return ret;}/* * receive rtsp header and set rtsp_ctrl  *              return status code : success *                               -1 : failure */int http_recv_header(struct stream_t *stream,struct http_header_t *http_hdr){    int ret = 0;    ret = http_recv_header_get(stream,http_hdr);    if(ret < 0) {	return -1;    }    ret = http_parse_response(stream->stream_ctrl->http_ctrl,http_hdr);    if(ret < 0) {	return -1;    }    return http_hdr->status_code;}/* * receive http message from stream->sock. *      header is guraranteed to be complete after this function, *      body should not be complete. *      so search Content-length and get all the body later. *               return status code : success *                               -1 : failure */int http_recv_header_get(struct stream_t *stream, struct http_header_t *http_hdr){    int ret = 0,i = 0,total = 0;      http_hdr->buffer_len = 0;    http_hdr->buffer = NULL;    total = 0;      do { /* get http reply */	http_hdr->buffer_len += BUFSIZE_1K;	http_hdr->buffer = (char *)xrealloc(http_hdr->buffer,					    http_hdr->buffer_len + 1);		i = recv_data(stream,http_hdr->buffer + total,http_hdr->buffer_len - total);	if(i <= 0) {	    display(MSDL_ERR,"http_recv_header error: recv_data() returned %d\n",i);	    goto failed;	}	total += i;  	http_hdr->buffer[total] = '\0';    } while(!http_is_entire_header(http_hdr));      /* http_hdr->buffer_size is length in buffer, not the malloc()ed size.  */    http_hdr->buffer_len = total;    http_hdr->buffer[total] = '\0';      /*     * actually 2 protocols uses http, so      * don't mess with stream_ctrl->*_ctrl     */    ret = http_response_parse(http_hdr);    if(ret < 0) {	display(MSDL_ERR,"response HTTP header parse failed\n");	goto failed;    }      /* push body back !!! */    if(http_hdr->body_len) {	stream_data_push_back(stream,http_hdr->body,http_hdr->body_len);    }      /* http_hdr->buffer *ONLY* contains header, no body follows */    memset(http_hdr->body,0,http_hdr->body_len);    /* dbg */    display(MSDL_DBG,"Resopnse header===========\n"	    "%s\n"	    "--(%d bytes)-------------------\n",	    http_hdr->buffer,(int)http_hdr->buffer_len);        /* success */    return http_hdr->status_code;      failed:    if(http_hdr->buffer) free(http_hdr->buffer);    http_hdr->buffer = NULL;    return -1;}/* table for base 64 */const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";/* * base64_encode : base 64 encode. * * enc:    string to base64 encode. * enclen: length of enc * out:    output base64 encoded result. * outmax: length of out (buffer length) * * copied from Mplayer/stream/http.c */int base64_encode(const void *enc,int enclen,char *out,int outsize){    unsigned char *encbuf;    int outlen;    unsigned int bits;    unsigned int shift;     encbuf = (unsigned char*)enc;    outlen = 0;    bits = 0;    shift = 0;    outsize &= ~3;      while( outlen < outsize ) {	if( enclen>0 ) {	    /* Shift in byte */	    bits <<= 8;	    bits |= *encbuf;	    shift += 8;	    /* Next byte     */	    encbuf++;	    enclen--;	} else if( shift>0 ) {	    /* Pad last bits to 6 bits - will end next loop */	    bits <<= 6 - shift;	    shift = 6;	} else {	    /*	      As per RFC 2045, section 6.8, 	      pad output as necessary: 0 to 2 '=' chars.	    */	    while( outlen & 3 ){		*out++ = '=';		outlen++;	    }  	    return outlen;	} 	/* Encode 6 bit segments */	while( shift>=6 ) {	    shift -= 6;	    *out = b64[ (bits >> shift) & 0x3F ];	    out++;	    outlen++;	}    }      /* output overflow */    return -1;}/* * add BASIC authentication string to header. *                return value: 0 */int http_add_basic_authentication(struct http_header_t *http_hdr,				  const char *username, const char *password){    char *auth = NULL, *user_pass = NULL, *b64_user_pass = NULL;    int encoded_len ,pass_len = 0, out_len;      int res = -1;    /* username cannot be NULL. */    if(http_hdr == NULL || username == NULL)  return -1;      if(password != NULL) {	pass_len = strlen(password);    }    user_pass = (char *)xmalloc(strlen(username) + pass_len + 2);    sprintf(user_pass, "%s:%s",username,(password == NULL) ? "" : password);      /* base64 encode with at least 33% more data than the original size. */    encoded_len = strlen(user_pass) * 2;    b64_user_pass = (char *)xmalloc(encoded_len);      out_len = base64_encode(user_pass,strlen(user_pass),			    b64_user_pass,encoded_len);    if(out_len < 0) {	fatal_error("Base64 output overflow!!\n");    }      b64_user_pass[out_len] = '\0';    auth = xmalloc(encoded_len + 22);      sprintf(auth,"Authorization: Basic %s",b64_user_pass);    http_set_field(http_hdr,auth);    res = 0;     free(user_pass);    free(b64_user_pass);    free(auth);        return res;}int http_print_authenticate_required(struct http_header_t *http_hdr){    char *auth = NULL;      auth = http_get_field(http_hdr,"WWW-Authenticate");    if(auth) { /* found!!!  */	char *auth_space = NULL;	auth_space = strstr(auth,"realm=");	if(auth_space != NULL) auth_space += 6;	display(MSDL_NOR,"authentication required %s!!\n",auth_space);    }    else {     /* not found */	display(MSDL_NOR,"authentication required!!\n");    }      return 0;}char *http_redirect_new_url(struct http_header_t *http_hdr){    char *loc = NULL;    loc = http_get_field(http_hdr,"Location");    if(loc) {	return strdup(loc);    }    else {	display(MSDL_ERR,"Location: field does not exist, maybe invalid redirection\n");	return NULL;    }}void http_set_uri(struct http_header_t *http_hdr,const char *uri){    if(http_hdr == NULL || uri == NULL) return;    http_hdr->uri = strdup(uri);}void http_set_method(struct http_header_t *http_hdr, const char *method){    if(http_hdr == NULL || method == NULL) return;    http_hdr->method = strdup(method);}char *http_request_get(struct http_header_t *http_hdr){    http_set_method(http_hdr,"GET");      return (http_build_request(http_hdr));}char *http_request_head(struct http_header_t *http_hdr){    http_set_method(http_hdr,"HEAD");      return (http_build_request(http_hdr));}char *http_request_post(struct http_header_t *http_hdr){    http_set_method(http_hdr,"POST");      return (http_build_request(http_hdr));}/* * make complete http_header_t. * the request string goes to http_hdr->buffer *             return value:   http_hdr->buffer ( built request ) */char *http_build_request(struct http_header_t *http_hdr){    char *ptr = NULL;    int len;    struct http_field_t *field;      if(http_hdr->uri == NULL) {	http_set_uri(http_hdr,"/");    }        /*     * culculate the request length.     */    /* method line */    len = strlen(http_hdr->method) + strlen(http_hdr->uri) + 12;    /* fields */    field = http_hdr->first_field;    while(field) {	len += strlen(field->field_name) + 2;	field = field->next;    }    /* CRLF */    len += 2;    /* request body */    if(http_hdr->body) {	len += http_hdr->body_len;    }      /*     * free the buffer which used 4 last request.     */    if(http_hdr->buffer) {	free(http_hdr->buffer);	http_hdr->buffer = NULL;    }      http_hdr->buffer_len = len;    http_hdr->buffer = xmalloc(len + 1); /* 1 for '\0' */        /*      * build the request     */    ptr = http_hdr->buffer;    /* method line */    ptr += sprintf(ptr,"%s %s HTTP/1.%d\r\n",		   http_hdr->method,http_hdr->uri,http_hdr->http_minor_version);    field = http_hdr->first_field;    /* fields */    while(field != NULL) {	ptr += sprintf(ptr,"%s\r\n",field->field_name);	field = field->next;    }    ptr += sprintf(ptr,"\r\n");      if(http_hdr->body != NULL) {	memcpy(ptr,http_hdr->body,http_hdr->body_len);    }        return http_hdr->buffer;}/* * concatinate http_hdr->buffer and response. * return value is new buffer size. (not counting NULL char) */int http_response_append(struct http_header_t *http_hdr,			 char *response,int len){    if(http_hdr == NULL || response == NULL || len < 0) return 0;        /* *** caution *** */    /* http_hdr->buffer_size does NOT include '\0' at the end. */      /*      if(http_hdr->buffer_size + len + 1 > HDR_SIZE_MAX) { // +1 for '\0'      display(MSDL_ERR,"%d maybe recv failed\n",http_hdr->buffer_size);      return -1;      }    */    http_hdr->buffer = (char *)xrealloc(http_hdr->buffer,					http_hdr->buffer_len + len + 1);    /* concat buffer. */    memcpy(http_hdr->buffer + http_hdr->buffer_len, response, len);    http_hdr->buffer_len += len;    http_hdr->buffer[http_hdr->buffer_len] = '\0'; /* terminate. */    return http_hdr->buffer_len;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -