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

📄 msdl.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************** *    msdl.c:  download management functions *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * See README for program usage and information. * See COPYING for license information. * * * 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. * ***********************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <getopt.h>#include <sys/time.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "progress.h"#include "network.h"#include "mmst.h"#include "mmsh.h"#include "http.h"#include "ftp.h"#include "rtsp.h"struct download_opts_t *set_dlopts_from_options(struct options_t *options,						struct download_opts_t *dlopts);static char *create_local_file_name(char *target_str,struct options_t *options);static int download_target(char *target_str,			   struct options_t *options,struct dlresult_t *result,			   char **local_name);static int prepare_download(char *target_str,struct options_t *options,			    struct url_t **url_ret,struct download_opts_t **dlopts_ret,			    char **local_name);static int do_download(const char *local_name,struct url_t *url,struct download_opts_t *dlopts);static int streaming_download(const char *local_file,struct url_t *url,			      struct download_opts_t *dlopts);static void display_protocol(struct stream_t *stream);static int filename_cmp(void *a,void *b);static int is_metafile(char *name);static int get_url_list_from_file(char *filename,struct list_h **ret);const char default_file_name_for_empty[] = "file";/* * meta_f ... 1 --> always metafile *            0 --> don't know, judge from name *           -1 --> NEVER. */struct target_t *new_target_t(char *name,int meta_f){    struct target_t *t = xmalloc(sizeof(struct target_t));    t->target_name = strdup(name);    t->metafile_f = meta_f;    return t;}void free_target_t(struct target_t *t){    if(!t) {	return;    }    free(t->target_name);    free(t);}struct options_t *new_options_t(void){    struct options_t *opt = xmalloc(sizeof(struct options_t));    memset(opt,0,sizeof(struct options_t));    return opt;}void free_options_t(struct options_t *opt){    if(!opt) {	return;    }      if(opt->protocol)       free(opt->protocol);    if(opt->local_filename) free(opt->local_filename);    if(opt->logfile)        free(opt->logfile);    if(opt->username)       free(opt->username);    if(opt->password)       free(opt->password);    if(opt->http_proxy)     free(opt->http_proxy);    if(opt->speed)          free(opt->speed);    if(opt->range)          free(opt->range);    if(opt->byterange)      free(opt->byterange);    free_list_h(opt->targets,(void (*)(void *))free_target_t);      free(opt);}struct download_opts_t *new_download_opts_t(void){    struct download_opts_t *dlopts = xmalloc(sizeof(struct download_opts_t));    memset(dlopts,0,sizeof(struct download_opts_t));        return dlopts;}struct download_opts_t *set_dlopts_from_options(struct options_t *options,						struct download_opts_t *dlopts){    /*      set download options, such as bandwidth, some mode, etc.      !!!! CAUTION !!!!      these options are applied to all download in target list.    */    if((options == NULL) || (dlopts == NULL)) {	return NULL;    }        if(options->bandwidth) {	dlopts->bandwidth = options->bandwidth;    }      if(options->no_passive_ftp_f) {	dlopts->no_passive_ftp = 1;    }        if(options->speed) {	dlopts->speed = strdup(options->speed);    }    if(options->range) {	dlopts->range = strdup(options->range);    }    if(options->byterange) {	dlopts->byterange = strdup(options->byterange);    }        if(options->auto_retry_times) {	dlopts->auto_retry = options->auto_retry_times;    }    if(options->resume) {	dlopts->resume_download = 1;    }    if(options->username) {	dlopts->username = strdup(options->username);    }    if(options->password) {	dlopts->password = strdup(options->password);    }    if(options->http_proxy) {	dlopts->http_proxy = strdup(options->http_proxy);    }    return dlopts;}void free_download_opts_t(struct download_opts_t *dlopts){    if(!dlopts) {	return;    }    if(dlopts->speed) free(dlopts->speed);    if(dlopts->range) free(dlopts->range);    if(dlopts->byterange) free(dlopts->byterange);    if(dlopts->username) free(dlopts->username);    if(dlopts->password) free(dlopts->password);        free(dlopts);}struct dlresult_t *new_dlresult_t(void){    struct dlresult_t *dlr = xmalloc(sizeof(struct dlresult_t));    memset(dlr,0,sizeof(struct dlresult_t));    return dlr;}void free_dlresult_t(struct dlresult_t *dlr){    if(!dlr) {	return;    }    if(dlr->success_list) free_list_h(dlr->success_list,free);    if(dlr->failed_list)  free_list_h(dlr->failed_list,free);      free(dlr);}/* * take 2 urls, a and b. only use filename at the end of url. *           return value:     0 ... same file *                       : non 0 ... file name differs */static int filename_cmp(void *a,void *b){    char *s = (char *)a,*t = (char *)b;    s = strrchr(s,'/') + 1;    t = strrchr(t,'/') + 1;        return strcmp(s,t);}/* * files with these extensions are regarded as metafiles. */char *metafile_prefixes[] = {    /* Windows Media metafiles */    "asx",    "wvx",    "wax",    /* Real Audio metafiles */    "ram",    "rpm",    "smi",};char *metafile_starts[] = {    "meta",};/* * judge if url 'name' is windows/real media metafile or not, from  * metafile_prefixes described above *            return value:   0  ... not *                            1  ... yes it is. */static int is_metafile(char *name){    int i = 0;    char *p = NULL;      if((p = strrchr(name,'.'))) {	p++;	for(i = 0; i < sizeof(metafile_prefixes)/sizeof(char *) ; i++) {	    if(!strcasecmp(metafile_prefixes[i],p)) return 1;	}    }      if((p = strrchr(name,'/'))) {	p++;	for(i = 0; i < sizeof(metafile_starts)/sizeof(char *) ; i++) {	    if(!strncasecmp(metafile_starts[i],p,strlen(metafile_starts[i]))) return 1;	}    }    return 0;}/* * get string(url) list from file 'filename' * for not downloading same URLs again and again, * this function returns list via "uniq" filter. * * @ret  string list ... success *       NULL        ... no url in file * * return value: count ... URLs appear in the file *                  -1 ... could not open file */static int get_url_list_from_file(char *filename,struct list_h **ret){    FILE *localfp = NULL;    struct list_h *url_list = NULL;    int linesize = BUFSIZE_1K;    char *line = xmalloc(linesize); /* 1024 bytes default */    char *p = NULL;    char *sep = NULL;    int url_len = 0;    int url_count = 0;    /*        try to download first url in the list       --> maybe playlist contain same url twice    */    if((localfp = fopen(filename,"rb")) == NULL) {	display(MSDL_ERR,"cannot open file %s\n",filename);	goto open_failed;    }    while(fgets(line,linesize,localfp)) {	while((line[strlen(line) - 1] != '\n')) { /* didn't read the whole line */	    linesize += BUFSIZE_1K;	    line = xrealloc(line,linesize);	    if(fgets(line + strlen(line),BUFSIZE_1K,localfp) == NULL) {		/* error or EOF */		break;	    }	}    	p = line;	while((sep = strstr(p,"://"))) { /* contains url string */	    /* protocol is alphabet */	    for(sep--; sep >= p && isalpha(*sep) ; sep--); 	    sep++;	    for(url_len = 0; is_url_valid_char(sep[url_len]); url_len++);	    sep[url_len] = '\0';      	    /* for not downloading same file again and again */	    if(sep[url_len - 1] != '/') { /*ignore directories */				if(search_list_h(url_list,sep,filename_cmp) == NULL) {		    /* same file not found */		    list_h_append(&url_list,strdup(sep));		    url_count++;		}		else {		    display(MSDL_VER,"file: <%s> is not uniq, ignore this\n",			    strrchr(sep,'/') + 1);		}	    }      	    p = &(sep[url_len]) + 1;	}    }            free(line);    fclose(localfp);    *ret = url_list;    return url_count;  open_failed:    free(line);    *ret = NULL;    return -1;}/* * main download manager function  * * 'target' is url or local file which contains url(s) to download *  * return value:       number of files which successfully donwloaded * */int msdl(struct target_t *target,struct options_t *options,struct dlresult_t *result){    int downloaded_files_count = 0;    int ret;        /*      set urls to download.    */    if(strstr(target->target_name,"://")) { /* network file case */	char *local_filename = NULL;		ret = download_target(target->target_name,			      options,			      result,			      &local_filename); /* local filename will be returned */		/* we got metafile from network --> have to download what's inside */	if((target->metafile_f != FORCE_NOT_METAFILE) && /* -1 is no-metafile flag */	   (is_metafile(target->target_name) || target->metafile_f == IS_METAFILE) &&	   (ret >= 0)) { /* download must be success(1) or already done(0)*/	    struct target_t *new_target = NULL;	    	    /* recursive download */                 /* DO NOT DO RECURSIVE AGAIN*/	    new_target = new_target_t(local_filename,FORCE_NOT_METAFILE);	    	    /* rcursive download file */	    downloaded_files_count += msdl(new_target,options,result);	    free_target_t(new_target);	}		if(local_filename) free(local_filename);    }    else { /* file list (local file) */	struct list_h *p = NULL;                  /* iterator */	struct list_h *target_str_list = NULL;    /* string   */	int ret = 0;	ret = get_url_list_from_file(target->target_name,&target_str_list);	if(ret < 0) { /*could not open file*/	    return 0;	}	else if(ret == 0) {	    display(MSDL_ERR,"input file \"%s\" does not contain any url\n",target->target_name);	    return 0;	}		/* download each files the list*/	for(p = target_str_list ; p ; p = p->next) {	    char *target_str = p->p;	    struct target_t *target_in_file = NULL;	    /*	      create file which contains downloaded data.	    */	    target_in_file = new_target_t(target_str,FORCE_NOT_METAFILE);	    downloaded_files_count += msdl(target_in_file,options,result);	    free_target_t(target_in_file);	}	free_list_h(target_str_list,free);    }      return downloaded_files_count;}/* * create local file name string from target_str and options->local_filename * return value: local file name to save, from target_str or options->local_filename *               NULL if invalid. */static char *create_local_file_name(char *target_str,struct options_t *options){    char *local_filename = NULL;        if(options->local_filename && strcmp(options->local_filename,"")) {	local_filename = strdup(options->local_filename);	/* cannot use options->local_filename again */	strcpy(options->local_filename,"");    }    else {	char *p = strrchr(target_str,'/');	if(p && p[1] != '\0') { /* do not allow local_filename to be "" (p[0] == '/' now)*/	    local_filename = strdup(p + 1);	}    }        return local_filename;}/* * download target_str ==> local_save_file * and append success/failure results to results list. * return value: 1 (do_download() return) ... success *               0 ... file already downloaded, and nothing to do *              -1 ... faliure */

⌨️ 快捷键说明

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