/* WebDownloader for X-Window * Copyright (C) 1999-2002 Koshelev Maxim * This Program is free but not GPL!!! You can't modify it * without agreement with author. You can't distribute modified * program but you can distribute unmodified program. * * 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. */ #include #include #if (defined(__unix__) || defined(unix)) && !defined(USG) #include #endif #include #include #include #include #include #include #include #include #include "var.h" #include "ftpd.h" #include "httpd.h" #include "hproxy.h" #include "locstr.h" #include "main.h" #include "dlist.h" #include "meter.h" #include "log.h" #include "mainlog.h" #include "signal.h" #include "savelog.h" #include "face/list.h" #include "face/buttons.h" #include "face/log.h" #include "face/edit.h" #include "face/addd.h" #include "face/fsface.h" #include "config.h" #include "ntlocale.h" #include "memwl.h" #include "schedule.h" #include "html.h" #include "filter.h" #include "sndserv.h" #include "xml.h" #include "face/passface.h" #include "face/saveload.h" #include #include tMLog *MainLog=NULL; d4xDownloadQueue *D4X_QUEUE=NULL; tQueue D4X_QTREE; tMeter *GlobalMeter=NULL; tMeter *LocalMeter=NULL; tMeter *GraphMeter=NULL; tMeter *GraphLMeter=NULL; tMsgQueue *LogsMsgQueue; int calc_curent_run(char *host,int port) { return (D4X_QUEUE->current_run(host,port)); }; int d4x_only_one_queue(){ if (D4X_QTREE.count()>1 || ((d4xDownloadQueue*)(D4X_QTREE.first()))->child.count()) return(0); return(1); }; static void d4x_qtree_for_each_rec(tQueue *q,d4xQTreeFunc dothis,void *a){ d4xDownloadQueue *dq=(d4xDownloadQueue*)(q->first()); while (dq){ d4xDownloadQueue *next=(d4xDownloadQueue *)(dq->prev); d4x_qtree_for_each_rec(&(dq->child),dothis,a); dothis(dq,a); dq=next; }; }; void d4x_qtree_for_each(d4xQTreeFunc dothis,void *a){ d4x_qtree_for_each_rec(&D4X_QTREE,dothis,a); }; //**********************************************/ typedef void (*SigactionHandler)(int); void _sig_pipe_handler_(){ }; int tMain::init() { TO_WAIT_IF_HERE=DONTRY2RUN=0; GVARS.SOCKETS=new d4x::SocketsHistory; ftpsearch=NULL; prev_speed_limit=0; list_to_delete=NULL; GlobalMeter=new tMeter; GlobalMeter->init(METER_LENGTH); LocalMeter=new tMeter; LocalMeter->init(METER_LENGTH); GraphMeter=new tMeter; GraphMeter->init(GRAPH_METER_LENGTH); GraphLMeter=new tMeter; GraphLMeter->init(GRAPH_METER_LENGTH); SpeedScheduler=new d4x::SpeedQueue; MainScheduler=new d4xScheduler; MainScheduler->load(); ALL_DOWNLOADS=new tDB; d4x::filters_load_rc(); LastReadedBytes=0; /* Create msgqueue for logs update */ MsgQueue=new tMsgQueue; MsgQueue->init(0); LogsMsgQueue=MsgQueue; SOUND_SERVER=new d4xSndServer; SOUND_SERVER->init_sounds(); /* setting up signal handlers */ struct sigaction action,old_action; action.sa_handler=SigactionHandler(my_main_quit); action.sa_flags=0;//SA_NOCLDSTOP; sigaction(SIGINT,&action,&old_action); sigaction(SIGTERM,&action,&old_action); action.sa_flags=0; action.sa_handler=SigactionHandler(_sig_pipe_handler_); sigaction(SIGPIPE,&action,&old_action); sigset_t oldmask,newmask; sigemptyset(&newmask); sigaddset(&newmask,SIGINT); sigaddset(&newmask,SIGTERM); pthread_sigmask(SIG_UNBLOCK,&newmask,&oldmask); server=new tMsgServer; if (server->init()){ perror(_("Can't init control socket!\n")); delete(server); return(-1); }; FaceForPasswords=new tFacePass; FaceForPasswords->load(); return(0); }; void create_new_queue(char *name,d4xDownloadQueue *papa){ d4xDownloadQueue *q=new d4xDownloadQueue; q->name.set(name); if (papa){ q->inherit_settings(papa); papa->subq_add(q); }else{ if (D4X_QTREE.last()) q->inherit_settings((d4xDownloadQueue*)D4X_QTREE.last(),CFG.GLOBAL_SAVE_PATH); D4X_QTREE.insert(q); }; if (CFG.WITHOUT_FACE==0){ q->qv.init(); q->init_pixmaps(); D4X_QVT->add(q,papa); if (!D4X_QUEUE) D4X_QVT->switch_remote(q); }else{ if (!D4X_QUEUE) D4X_QUEUE=q; }; }; void tMain::init_qtree(tQueue *list,d4xDownloadQueue *papa){ d4xDownloadQueue *q=(d4xDownloadQueue *)(list->first()); while(q){ if (q->SpdLmt) SpeedScheduler->insert(q); q->parent=papa; if (CFG.WITHOUT_FACE==0){ D4X_QVT->add(q,papa); if (q->IamDefault) D4X_QVT->switch_remote(q); }else{ if (q->IamDefault){ D4X_QUEUE=q; }; }; init_qtree(&(q->child),q); try_to_run_run(q); try_to_run_wait(q); q=(d4xDownloadQueue *)(q->prev); }; }; void tMain::load_defaults() { MainLog->add(_("Loading default list of downloads"),LOG_OK|LOG_DETAILED); read_list(); if (D4X_QTREE.count()){ init_qtree(&D4X_QTREE); if (!D4X_QUEUE){ d4xDownloadQueue *q=(d4xDownloadQueue *)(D4X_QTREE.first()); if (CFG.WITHOUT_FACE){ D4X_QUEUE=q; }else{ D4X_QVT->switch_remote(q); }; }; }else{ create_new_queue("Main"); }; if (!CFG.WITHOUT_FACE) D4X_QUEUE->qv.set_shift(CFG.CLIST_SHIFT); }; void tMain::init_main_log() { MainLog=new tMLog; MainLog->init(CFG.MAX_MAIN_LOG_LENGTH); if (CFG.WITHOUT_FACE==0) MainLog->init_list(GTK_TREE_VIEW(MainLogList)); MainLog->reinit_file(); MainLog->add("----------------------------------------",LOG_FROM_SERVER); }; void tMain::redraw_logs() { int limit = 12; GList *tmplist=NULL; while (limit>0) { limit--; tLogMsg *Msg=(tLogMsg*)MsgQueue->first(); if (Msg) { if (Msg->type&MQT_MY){ if (Msg->what){ if (Msg->which->freezed_flag==0){ tmplist=log_window_freeze(tmplist,Msg->which); }; log_window_add_string(Msg->which,Msg->what); }else{ del_first_from_log(Msg->which); }; }; if (Msg->type&MQT_COM){ if (Msg->what){ if (Msg->which==D4X_LOG_DISPLAY.log) d4x_main_log_add_string(Msg->what); }else{ if (Msg->which==D4X_LOG_DISPLAY.log) d4x_main_log_del_string(); }; }; Msg->which->unlock(); Msg->which->ref_dec(); MsgQueue->del(Msg); delete(Msg); }else break; }; while(tmplist){ tmplist=log_window_unfreeze(tmplist); }; }; void tMain::absolute_delete_download(tDownload *what) { DBC_RETURN_IF_FAIL(what!=NULL); if (CFG.WITHOUT_FACE==0 && D4X_LOG_DISPLAY.papa==what) D4X_LOG_DISPLAY.papa=NULL; DQV(what).remove(what); d4xDownloadQueue *q=what->myowner->PAPA; q->del(what); ALL_DOWNLOADS->del(what); FaceForPasswords->stop_matched(what); delete(what); }; void tMain::del_completed(d4xDownloadQueue *queue) { MainLog->add(_("Delete completed downloads"),LOG_OK|LOG_DETAILED); del_all_from_list(DL_COMPLETE,queue); }; void tMain::rerun_failed(){ tDownload *temp=D4X_QUEUE->first(DL_STOP); while (temp) { continue_download(temp); temp=D4X_QUEUE->first(DL_STOP); }; }; void tMain::del_fataled(d4xDownloadQueue *queue){ MainLog->add(_("Delete failed downloads"),LOG_OK|LOG_DETAILED); del_all_from_list(DL_STOP,queue); }; void tMain::del_all_from_list(int list,d4xDownloadQueue *queue){ tDownload *temp=queue?queue->first(list):D4X_QUEUE->first(list); while (temp) { tDownload *next=(tDownload *)(temp->prev); if (!temp->protect){ absolute_delete_download(temp); }; temp=next; }; }; void tMain::del_all() { if (D4X_QUEUE->count()) MainLog->add(_("Clear queue of downloads"),LOG_ERROR); tDownload *temp=D4X_QUEUE->first(DL_RUN); while (temp) { stop_download(temp); temp=D4X_QUEUE->first(DL_RUN); }; temp=D4X_QUEUE->first(DL_STOPWAIT); while (temp) { if (!temp->protect) temp->action=ACTION_DELETE; temp=(tDownload *)(temp->prev); }; del_all_from_list(DL_PAUSE); del_all_from_list(DL_WAIT); del_all_from_list(DL_STOP); del_all_from_list(DL_COMPLETE); del_all_from_list(DL_LIMIT); }; int tMain::run_new_thread(tDownload *what) { DBC_RETVAL_IF_FAIL(what!=NULL,-1); pthread_attr_t attr_p; what->status=READY_TO_RUN; what->STOPPED_BY_USER=false; if (!what->LOG) { what->LOG=new tLog; what->LOG->ref_inc(); if (CFG.WITHOUT_FACE) what->LOG->init(2); // two strings in log if run without interface else what->LOG->init(CFG.MAX_LOG_LENGTH); }; if (what->info.proto==D_PROTO_SEARCH){ what->WL=new tMemoryWL; ((tMemoryWL *)(what->WL))->set_log(what->LOG); }else{ what->WL=new tDefaultWL; ((tDefaultWL *)(what->WL))->set_log(what->LOG); }; what->update_trigers(); what->config->redirect_count=0; what->Size.reset(); // no need update size if (what->SpeedLimit==NULL) what->SpeedLimit=new d4x::Speed; /* set speed limitation */ if (what->split && what->split->NumOfParts){ what->SpeedLimit->base = what->config->speed/what->split->NumOfParts; }else{ what->SpeedLimit->base = what->config->speed; }; what->set_initial_speedlimit(); SpeedScheduler->insert(what->SpeedLimit); if (what->editor) what->editor->disable_ok_button(); MainLog->myprintf(LOG_OK|LOG_DETAILED,_("Run new thread for %z"),what); pthread_attr_init(&attr_p); pthread_attr_setdetachstate(&attr_p,PTHREAD_CREATE_JOINABLE); pthread_attr_setscope(&attr_p,PTHREAD_SCOPE_SYSTEM); if (pthread_create(&what->thread_id,&attr_p,download_last,(void *)what)){ MainLog->add(_("Can't run new thread for downloading!"),LOG_ERROR); return(-1); }; return(0); }; void tMain::stop_split(tDownload *what){ DBC_RETURN_IF_FAIL(what!=NULL); tDownload *tmp=what->split->next_part; int a=1; while(tmp){ a++; if (tmp->split->run) stop_thread(tmp); else what->split->stopcount+=1; tmp=tmp->split?tmp->split->next_part:NULL; }; what->split->stopcount+=what->split->NumOfParts-a; }; tDownload *tMain::find_url(const d4x::URL &adr){ tDownload tmp; tmp.info=adr; tDownload *a=ALL_DOWNLOADS->find(&tmp); return(a); }; void tMain::stop_download_url(const d4x::URL &adr){ tDownload *a=find_url(adr); if (a) stop_download(a); }; void tMain::continue_download_url(const d4x::URL &adr){ tDownload *a=find_url(adr); if (a) continue_download(a); }; void tMain::delete_download_url(const d4x::URL &adr){ tDownload *a=find_url(adr); if (a) delete_download(a); }; void tMain::stop_download(tDownload *what) { DBC_RETURN_IF_FAIL(what!=NULL); int owner=what->owner(); if (owner==DL_STOPWAIT && what->action!=ACTION_DELETE) { what->action=ACTION_STOP; return; }; d4xDownloadQueue *papa=what->myowner->PAPA; if (papa->is_first(DL_SIZEQUERY,what)){ stop_thread(what); return; }; if (owner==DL_RUN) { papa->del(what); MainLog->myprintf(LOG_WARNING,_("Downloading of file %s from %s was terminated [by user]"), what->info.file.c_str(), what->info.host.c_str()); stop_thread(what); if (what->split) stop_split(what); papa->add(what,DL_STOPWAIT); what->ActStatus.clear(); } else { if (owner==DL_WAIT || owner==DL_LIMIT || owner==DL_SIZEQUERY) { what->sizequery=0; FaceForPasswords->stop_matched(what); papa->del(what); papa->add(what,DL_PAUSE); what->ActStatus.clear(); try_to_run_wait(papa); }; }; }; int tMain::delete_download(tDownload *what,int flag) { if (!what) return 0; if (what->protect) return 0; if (what->owner()==DL_RUN) stop_download(what); d4xDownloadQueue *papa=what->myowner->PAPA; if (papa->is_first(DL_SIZEQUERY,what)){ papa->del(what); stop_thread(what); papa->add(what,DL_STOPWAIT); what->action=ACTION_DELETE; sizequery_run_first(papa); return(0); }; if (what->owner()==DL_STOPWAIT){ if (flag) what->action=ACTION_REAL_DELETE; else what->action=ACTION_DELETE; return 0; }; MainLog->myprintf(LOG_WARNING,_("Delete file %s from queue of downloads"),what->info.file.c_str()); if (flag) what->remove_tmp_files(); absolute_delete_download(what); return 1; }; void tMain::try_to_run_split(tDownload *what){ DBC_RETURN_IF_FAIL(what!=NULL); if (what->split->runcount>=what->split->NumOfParts) return; if (what->status==DOWNLOAD_GO || what->status==DOWNLOAD_COMPLETE){ tDownload *dwn=what->split->next_part; while (dwn && FaceForPasswords->limit_check(what)==0){ if (dwn->split->run==0){ if (run_new_thread(dwn)) return; dwn->split->run=1; what->split->runcount+=1; FaceForPasswords->limit_inc(what); }; dwn=dwn->split->next_part; }; }; }; int tMain::try_to_run_download(tDownload *what){ DBC_RETVAL_IF_FAIL(what!=NULL,-1); time_t NOW; time(&NOW); d4xDownloadQueue *papa=what->myowner->PAPA; if (papa->count(DL_RUN)<50) { what->SpeedCalc.reset(); what->Start=what->Pause=time(NULL); if (what->config==NULL){ what->config=new tCfg; what->set_default_cfg(); }; // to avoid old info in columns if (CFG.WITHOUT_FACE==0) DQV(what).change_data(what->list_iter,PAUSE_COL); if (what->split){ what->finfo.size=-1; what->split->FirstByte=0; what->split->LastByte=-1; what->split->reset(); what->config->rollback=0; // what->config->ftp_recurse_depth = 1; what->split->grandparent=what; // what->config->http_recurse_depth = 1; }; if (run_new_thread(what)) return -1; if (what->split){ what->split->runcount=1; what->split->run=1; }; return 1; }; return 0; }; void tMain::insert_into_wait_list(tDownload *what, d4xDownloadQueue *dq){ if (CFG.WITHOUT_FACE){ dq->add(what); }else{ tDownload *temp=dq->last(DL_WAIT); if (!temp || dq->qv.get_row_num(temp) < dq->qv.get_row_num(what)) dq->add(what); else { temp=dq->first(DL_WAIT); while (temp && dq->qv.get_row_num(temp) < dq->qv.get_row_num(what)) temp=(tDownload*)(temp->prev); dq->insert_before(what,temp); }; D4X_QVT->update(dq); }; }; void tMain::continue_download(tDownload *what) { if (CFG.OFFLINE_MODE) return; if (!what) return; switch (what->owner()) { case DL_SIZEQUERY: break; case DL_STOPWAIT: if (what->action!=ACTION_DELETE && what->action!=ACTION_REAL_DELETE) what->action=ACTION_CONTINUE; break; case DL_RUN: stop_download(what); if (what->owner()==DL_STOPWAIT){ what->action=ACTION_CONTINUE; break; }; default: MainLog->myprintf(LOG_OK,_("Continue downloading of file %s from %s..."), what->info.file.c_str(), what->info.host.c_str()); d4xDownloadQueue *papa=what->myowner->PAPA; if (CFG.ALLOW_FORCE_RUN && what->owner()!=DL_PAUSE && try_to_run_download(what)) { papa->del(what); papa->add(what,DL_RUN); } else { papa->del(what); insert_into_wait_list(what,papa); try_to_run_wait(papa); }; }; what->Attempt.clear(); what->finfo.size=-1; }; void tMain::add_dir(tDownload *parent,int http) { if (parent==NULL || parent->DIR==NULL) return; tDownload *temp=parent->DIR->last(); d4xDownloadQueue *q=D4X_QUEUE; D4X_QUEUE=parent->myowner->PAPA; while(temp) { parent->DIR->del(temp); int totop=parent->config->ftp_dirontop && temp->finfo.type==T_DIR; tDownload *ex=add_downloading(temp,totop); if (ex) { if (ex->config && ex->config->http_recurse_depthconfig->http_recurse_depth && ex->myowner==parent->myowner){ ex->config->http_recurse_depth=temp->config->http_recurse_depth; continue_download(ex); }; delete temp; }; temp=parent->DIR->last(); }; D4X_QUEUE=q; }; void tMain::speed_calculation(tDownload *what){ DBC_RETURN_IF_FAIL(what!=NULL); time_t NOWTMP; time(&NOWTMP); switch(what->finfo.type) { case T_FILE:{ time_t newdiff=NOWTMP-what->Start; time_t difdif=what->Difference-newdiff; /* detecting clock skew */ if (difdif<-1800) what->Start+=difdif; else if (difdif>1800) what->Start-=difdif; what->Difference=NOWTMP-what->Start; int REAL_SIZE=what->finfo.size; if (REAL_SIZE==0 && what->who!=NULL) what->finfo.size=REAL_SIZE=what->who->another_way_get_size(); if (what->who) what->Size=what->get_loaded(); what->Remain=REAL_SIZE-what->Size; if (what->Difference!=0 && what->who) { what->Speed=what->SpeedCalc.speed(); }; }; }; }; void tMain::print_info(tDownload *what) { DBC_RETURN_IF_FAIL(what!=NULL); if (CFG.WITHOUT_FACE){ speed_calculation(what); return; }; d4xDownloadQueue *PAPA=what->myowner->PAPA; char data[MAX_LEN]; int downloading_started=0; if (what->who) { what->ActStatus=what->who->get_status(); if (what->ActStatus==D_DOWNLOAD || what->status==DOWNLOAD_COMPLETE || what->status==DOWNLOAD_FATAL){ downloading_started=1; if (!what->who->reget()) what->ActStatus=D_DOWNLOAD_BAD; }; if (!what->ActStatus) { what->ActStatus.reset(); // DQV(what).set_run_icon(what); }; }; switch(what->finfo.type) { case T_FILE:{ if (what->finfo.type!=what->finfo.oldtype) DQV(what).change_data(what->list_iter,FILE_TYPE_COL,_("file")); fsize_t REAL_SIZE=what->filesize(); DQV(what).change_data(what->list_iter,FULL_SIZE_COL,make_number_nice(REAL_SIZE,PAPA->NICE_DEC_DIGITALS)); what->Size=what->get_loaded(); what->Remain=REAL_SIZE-what->Size; if (!what->Remain && what->Remain>=0) DQV(what).change_data(what->list_iter,REMAIN_SIZE_COL, make_number_nice(fsize_t(what->Remain),PAPA->NICE_DEC_DIGITALS)); time_t NOWTMP; time(&NOWTMP); if (what->Start>0) { time_t newdiff=NOWTMP-what->Start; time_t difdif=what->Difference-newdiff; /* detecting clock skew */ if (difdif<-1800) what->Start+=difdif; else if (difdif>1800) what->Start-=difdif; what->Difference=NOWTMP-what->Start; DQV(what).change_data(what->list_iter,TIME_COL,convert_time(newdiff,PAPA->TIME_FORMAT)); }; if (!what->Size) { DQV(what).change_data(what->list_iter,DOWNLOADED_SIZE_COL, make_number_nice(fsize_t(what->Size),PAPA->NICE_DEC_DIGITALS)); time_t Pause=NOWTMP; if (Pause - what->Pause > 4) DQV(what).change_data(what->list_iter,PAUSE_COL); what->Pause = Pause; } else { if (what->status==DOWNLOAD_GO) { int Pause=NOWTMP-what->Pause; if (Pause>=30) DQV(what).change_data(what->list_iter,PAUSE_COL,convert_time(Pause,PAPA->TIME_FORMAT)); }; }; what->Percent=100; if (REAL_SIZE!=0) what->Percent=float((fsize_t(what->Size)*double(100))/double(REAL_SIZE)); /* setting new title of log*/ if (CFG.USE_MAINWIN_TITLE){ char title[MAX_LEN]; std::string rfile=hexed_string(what->info.file); sprintf(title,"%2.0f%% %lli/%lli %s",what->Percent,fsize_t(what->Size),REAL_SIZE,rfile.c_str()); log_window_set_title(what,title); log_window_set_split_info(what); }; DQV(what).set_run_icon(what); if (!what->Size) { DQV(what).set_percent(what->list_iter,what->Percent); }; what->Size.reset(); /* Speed calculation */ if (what->Difference!=0 && what->who) { what->Speed=what->SpeedCalc.speed(); if (!what->Speed){ DQV(what).change_data(what->list_iter,SPEED_COL, make_number_nice(fsize_t(what->Speed),PAPA->SPEED_FORMAT?2:0)); what->Speed.reset(); }; if (what->finfo.size>0 && what->Speed>0){ fsize_t tmp=(REAL_SIZE-what->Size)/what->Speed; if (tmp>=0 && tmp<24*3660) { DQV(what).change_data(what->list_iter,ELAPSED_TIME_COL, convert_time(tmp,PAPA->TIME_FORMAT)); } else DQV(what).change_data(what->list_iter,ELAPSED_TIME_COL,"..."); } else DQV(what).change_data(what->list_iter,ELAPSED_TIME_COL,"..."); }; break; }; case T_DIR:{ if (what->finfo.type!=what->finfo.oldtype) DQV(what).change_data(what->list_iter,FILE_TYPE_COL,_("dir")); break; }; case T_LINK:{ if (what->finfo.type!=what->finfo.oldtype) DQV(what).change_data(what->list_iter,FILE_TYPE_COL,_("link")); break; }; case T_DEVICE:{ if (what->finfo.type!=what->finfo.oldtype) DQV(what).change_data(what->list_iter,FILE_TYPE_COL,_("device")); break; }; default: if (what->finfo.type!=what->finfo.oldtype) DQV(what).change_data(what->list_iter,FILE_TYPE_COL,"???"); }; if (what->finfo.type==T_DIR || what->finfo.type==T_NONE){ if (what->who) what->Size=what->who->get_readed(); if (!what->Size) { DQV(what).change_data(what->list_iter,DOWNLOADED_SIZE_COL, make_number_nice(fsize_t(what->Size),PAPA->NICE_DEC_DIGITALS)); what->Size.reset(); }; }; if (!what->Attempt) { what->Attempt.reset(); if (what->config->number_of_attempts > 0) DQV(what).change_data(what->list_iter,TREAT_COL, boost::lexical_cast(fsize_t(what->Attempt))+"/"+ boost::lexical_cast(what->config->number_of_attempts)); else DQV(what).change_data(what->list_iter,TREAT_COL,boost::lexical_cast(fsize_t(what->Attempt))); }; what->finfo.oldtype=what->finfo.type; }; void tMain::redirect(tDownload *what,d4xDownloadQueue *dq) { DBC_RETURN_IF_FAIL(what!=NULL); what->config->redirect_count+=1; if (what->config->redirect_count>10){ what->delete_who(); MainLog->myprintf(LOG_ERROR,_("Too many redirections!"),what); dq->add(what,DL_COMPLETE); what->finfo.type=T_NONE; return; }; d4x::URL addr=what->redirect_url(); if (addr.is_valid()) { /* if (what->config->leave_server==0 && equal_uncase(addr->host.get(),what->info->host.get())==0){ MainLog->myprintf(LOG_ERROR,_("Redirection from [%z] to the different host forbidden by download's preferences!"),what); D4X_QUEUE->add(what,DL_COMPLETE); delete(addr); return; }; */ if (addr==what->info && equal(what->config->referer.get(),std::string(what->info).c_str())){ MainLog->myprintf(LOG_ERROR,_("Redirection from [%z] to the same location!"),what); dq->add(what,DL_COMPLETE); return; }; if (ALL_DOWNLOADS->find(addr)) { dq->add(what,DL_COMPLETE); return; }; ALL_DOWNLOADS->del(what); what->config->referer.set(std::string(what->info).c_str()); if (addr.file==what->info.file) what->restart_from_begin=1; what->info=addr; ALL_DOWNLOADS->insert(what); tDownload *temp=dq->first(DL_WAIT); if (temp) dq->insert_before(what,temp); else dq->add(what,DL_WAIT); // normalize_path(what->get_SavePath()); what->finfo.type=what->status=0; what->finfo.size=-1; if (CFG.WITHOUT_FACE==0){ dq->qv.change_data(what->list_iter,URL_COL,what->info); dq->qv.set_filename(what); for (int i=FILE_TYPE_COL;ilist_iter,i,""); }; }else{ MainLog->myprintf(LOG_ERROR,_("Redirection from [%z] to nowhere!"),what); dq->add(what,DL_COMPLETE); what->finfo.type=T_NONE; }; what->delete_who(); }; void tMain::post_stopping(tDownload *what){ /* dispose tSegmentator only for main thread */ if (what->segments){ delete(what->segments); what->segments=NULL; }; if (what->split && what->split->cond){ delete(what->split->cond); what->split->cond=NULL; }; if (what->config->isdefault && what->editor==NULL){ delete(what->config); what->config=NULL; }; if (what->editor) what->editor->enable_ok_button(); FaceForPasswords->stop_matched(what); }; void tMain::prepare_for_stoping_pre(tDownload *what){ MainLog->myprintf(LOG_OK|LOG_DETAILED,_("Prepare thread %i of [%z] for stoping"),what->split?what->split->thread_num:1,what); if (what->SpeedLimit) SpeedScheduler->del(what->SpeedLimit); delete (what->SpeedLimit); what->SpeedLimit=NULL; if (what->WL){ delete(what->WL); what->WL=NULL; }; }; void tMain::prepare_for_stoping(tDownload *what) { DBC_RETURN_IF_FAIL(what!=NULL); prepare_for_stoping_pre(what); if (what->split){ what->split->grandparent->split->stopcount+=1; FaceForPasswords->limit_dec(what->split->grandparent); // what->split->run=0; }else FaceForPasswords->limit_dec(what); }; void tMain::case_download_completed(tDownload *what){ DBC_RETURN_IF_FAIL(what!=NULL); d4xDownloadQueue *papa=what->myowner->PAPA; papa->del(what); if (what->finfo.type==T_REDIRECT) { MainLog->myprintf(LOG_OK,_("Redirect from %z"),what); redirect(what,papa); real_stop_thread(what); post_stopping(what); }else{ papa->add(what,DL_COMPLETE); if (what->file_type()==T_DIR) { MainLog->myprintf(LOG_OK,_("Downloading of directory %z was completed"),what); if (what->config->ftp_recurse_depth!=1) add_dir(what); } else { fsize_t bytes = what->finfo.size==0 ? what->who->get_readed():what->finfo.size; MainLog->myprintf(LOG_OK,_("Downloading of file %z (%ll bytes) was completed at speed %ll bytes/sec"),what,bytes,fsize_t(what->Speed)); if (what->config->http_recurse_depth!=1 && what->DIR) add_dir(what,1); }; real_stop_thread(what); post_stopping(what); if (papa->AUTODEL_COMPLETED && what->protect==0) { MainLog->myprintf(LOG_WARNING|LOG_DETAILED,_("%z was deleted from queue of downloads as completed download"),what); absolute_delete_download(what); }; }; }; void tMain::case_download_failed(tDownload *what){ DBC_RETURN_IF_FAIL(what!=NULL); d4xDownloadQueue *papa=what->myowner->PAPA; papa->del(what); papa->add(what,DL_STOP); MainLog->myprintf(LOG_ERROR,_("Downloading of file %z was terminated by fatal error"),what); if (papa->AUTODEL_FAILED && what->protect==0) { MainLog->myprintf(LOG_WARNING|LOG_DETAILED,_("%z was deleted from queue of downloads as failed download"),what); absolute_delete_download(what); }; }; void tMain::main_circle_first(tDownload *dwn){ /* look for stopped threads */ tDownload *grandpapa=dwn; prepare_for_stoping(dwn); real_stop_thread(dwn); if (dwn->split){ grandpapa=dwn->split->grandparent; if (grandpapa->split->stopcount!=grandpapa->split->NumOfParts && grandpapa->split->prepared) return; }; int status=grandpapa->status; post_stopping(grandpapa); d4xDownloadQueue *papa=grandpapa->myowner->PAPA; if (status==DOWNLOAD_REAL_STOP || status==DOWNLOAD_COMPLETE || status==DOWNLOAD_FATAL) { papa->del(grandpapa); papa->add(grandpapa,DL_PAUSE); switch(grandpapa->action){ case ACTION_REAL_DELETE: delete_download(grandpapa,1); break; case ACTION_DELETE: delete_download(grandpapa,0); break; case ACTION_CONTINUE: continue_download(grandpapa); grandpapa->action=ACTION_NONE; break; case ACTION_STOP: grandpapa->action=ACTION_NONE; break; case ACTION_FAILED: grandpapa->action=ACTION_NONE; papa->del(grandpapa); papa->add(grandpapa,DL_STOP); break; case ACTION_SIZEQUERY: move_to_sizequery(grandpapa); break; }; }; }; static bool _alt_equal_host_(tDownload *dwn,d4x::Alt *alt){ return alt->info.host==dwn->info.host; }; int tMain::try_to_switch(tDownload *dwn){ if (dwn->ALTS==0 || dwn->ALTS->LST.empty()) return(0); d4xAltList *ALTS=dwn->ALTS; std::list::iterator alt=std::find_if(ALTS->LST.begin(), ALTS->LST.end(), std::bind1st(std::ptr_fun(_alt_equal_host_),dwn)); if (alt!=ALTS->LST.end()) alt++; if (alt==ALTS->LST.end()){ // first switching, add this url to its own alternates d4x::Alt *newalt=new d4x::Alt; newalt->info=dwn->info; dwn->ALTS->lock.lock(); dwn->ALTS->add(newalt); dwn->ALTS->lock.unlock(); alt=ALTS->LST.begin(); }; if (ALL_DOWNLOADS->find((*alt)->info)){ return(0); }; ALL_DOWNLOADS->del(dwn); dwn->info=(*alt)->info; ALL_DOWNLOADS->insert(dwn); FaceForPasswords->set_do_not_run(1); prepare_for_stoping(dwn); real_stop_thread(dwn); if (run_new_thread(dwn)) return(0); FaceForPasswords->limit_inc(dwn); FaceForPasswords->set_do_not_run(0); if (dwn->split) dwn->split->stopcount-=1; return(1); }; int tMain::try_to_switch_split(tDownload *dwn,tDownload *gp){ if (gp==dwn) return(try_to_switch(dwn)); if (gp->ALTS==NULL || gp->ALTS->LST.empty()) return(0); int n=dwn->split->alt+1; std::list::iterator alt=gp->ALTS->LST.begin(); advance(alt,n); if (alt!=gp->ALTS->LST.end()){ dwn->split->alt+=1; dwn->info=(*alt)->info; }else{ dwn->info=gp->info; }; dwn->split->run=0; FaceForPasswords->set_do_not_run(1); prepare_for_stoping(dwn); gp->split->stopcount-=1; //to avoid wrong stopcount real_stop_thread(dwn); try_to_run_split(gp); FaceForPasswords->set_do_not_run(0); return(1); }; void tMain::check_split(tDownload *dwn){ tDownload *grandparent=dwn->split->grandparent; if (dwn->status==DOWNLOAD_FATAL){ if (try_to_switch_split(dwn,grandparent)) return; stop_download(grandparent); grandparent->action=ACTION_FAILED; main_circle_first(dwn); try_to_run_wait(grandparent->myowner->PAPA); return; }; if (grandparent->split->prepared){ // we need to check overlaping event here for splited downloads // just find best part to download, and go! :-) if (dwn->WL->is_overlaped() || dwn->status==DOWNLOAD_COMPLETE){ if (dwn->find_best_split() && dwn && dwn->who->reget()){ real_stop_thread(dwn); prepare_for_stoping_pre(dwn); dwn->split->cond->inc(); run_new_thread(dwn); return; }; }; prepare_for_stoping(dwn); try_to_run_split(grandparent); if (dwn!=grandparent) real_stop_thread(dwn); if (grandparent->split->NumOfParts==grandparent->split->stopcount) main_circle_second(grandparent); }else{ try_to_run_split(grandparent); if (grandparent->status==DOWNLOAD_COMPLETE || grandparent->status==DOWNLOAD_FATAL) prepare_for_stoping(grandparent); main_circle_second(grandparent); }; }; void tMain::main_circle_second(tDownload *dwn){ /* look for completeted or faild threads */ int failed=0,completed=0; d4xDownloadQueue *papa=dwn->myowner->PAPA; dwn->status_cp=dwn->status; switch(dwn->status) { case DOWNLOAD_COMPLETE:{ if (dwn->segments) dwn->segments->complete(); print_info(dwn); //to avoid wrong percentage after completing case_download_completed(dwn); completed=1; break; }; case DOWNLOAD_FATAL:{ if (dwn->split==NULL && try_to_switch(dwn)) return; case_download_failed(dwn); real_stop_thread(dwn); post_stopping(dwn); failed=1; break; }; }; int paparun=papa->count(DL_RUN); if (paparun==0){ papa->speed.reset(); if (!CFG.WITHOUT_FACE) D4X_QVT->update_speed(papa); }; if (completed){ if (paparun==0 && papa->count(DL_WAIT)==0) SOUND_SERVER->add_event(SND_QUEUE_FINISH); else SOUND_SERVER->add_event(SND_COMPLETE); try_to_run_wait(papa); }; if (failed){ try_to_run_wait(papa); SOUND_SERVER->add_event(SND_FAIL); }; }; void tMain::main_circle_nano1(){ int i=10; D4X_UPDATE.lock(); while(D4X_UPDATE.first && i>0){ tDownload *dwn=D4X_UPDATE.first; if (dwn->owner()==DL_RUN){ if (dwn->split) try_to_run_split(dwn); if (dwn->myowner->PAPA==D4X_QUEUE){ print_info(dwn); }; if (dwn->myowner && dwn->myowner->PAPA && !CFG.WITHOUT_FACE) D4X_QVT->update_speed(dwn->myowner->PAPA); }; D4X_UPDATE.del(); i--; }; D4X_UPDATE.unlock(); }; void tMain::main_circle_nano2(){ if (CFG.OFFLINE_MODE) return; D4X_UPDATE.lock_s(); D4X_UPDATE.lock(); int i=0; while (D4X_UPDATE.first_s){ tDownload *dwn=D4X_UPDATE.first_s; tDownload *gp=dwn; D4X_UPDATE.del_s(); D4X_UPDATE.del(dwn); if (dwn->split) gp=dwn->split->grandparent; // printf("%p %p\n",dwn,gp); switch(gp->owner()){ case DL_RUN: if (dwn->split){ check_split(dwn); break; }else{ if (dwn->WL->is_overlaped() && dwn->status==DOWNLOAD_COMPLETE){ real_stop_thread(dwn); prepare_for_stoping_pre(dwn); run_new_thread(dwn); break; }; prepare_for_stoping(gp); }; main_circle_second(gp); break; case DL_STOPWAIT: main_circle_first(dwn); break; case DL_SIZEQUERY:{ real_stop_thread(dwn); prepare_for_stoping(dwn); d4xDownloadQueue *papa=dwn->myowner->PAPA; print_info(dwn); papa->del(dwn); if (dwn->action==DL_WAIT || dwn->action==DL_SIZEQUERY){ dwn->sizequery=0; insert_into_wait_list(dwn,papa); }else{ papa->add(dwn,dwn->action); }; sizequery_run_first(papa); if (dwn->editor) dwn->editor->enable_ok_button(); break; }; default: break; }; if (i++>5) break; }; D4X_UPDATE.unlock(); D4X_UPDATE.unlock_s(); }; int tMain::set_auto_run(int a){ int old=DONTRY2RUN; DONTRY2RUN=a; return(old); }; void tMain::try_to_run_run(d4xDownloadQueue *papa){ tDownload *temp=papa->first(DL_RUN); while(temp) { tDownload *temp_next=(tDownload *)(temp->prev); int rvalue=try_to_run_download(temp); if (rvalue<0){ papa->del(temp); papa->add(temp,DL_WAIT); }else{ FaceForPasswords->match_and_check(temp,1); FaceForPasswords->limit_to_run(temp); }; temp=temp_next; }; }; void tMain::try_to_run_wait(d4xDownloadQueue *papa){ if (DONTRY2RUN) return; tDownload *temp=papa->first(DL_WAIT); while(temp && papa->count(DL_RUN)MAX_ACTIVE) { tDownload *temp_next=(tDownload *)(temp->prev); if (FaceForPasswords->match_and_check(temp)==0){ FaceForPasswords->limit_to_run(temp); int rvalue=try_to_run_download(temp); if (rvalue<0){ break; }; if (rvalue) { papa->del(temp); papa->add(temp,DL_RUN); }; }; temp=temp_next; }; }; void tMain::main_circle() { if (ftpsearch) ftpsearch->cycle(); speed(); MainScheduler->run(this); if (CFG.WITHOUT_FACE==0){ prepare_buttons(); D4X_UPDATE.update(D4X_QUEUE->get_queue(DL_RUN)); }; GVARS.SOCKETS->kill_old(); }; void tMain::set_speed(int speed){ CFG.SPEED_LIMIT=speed; if (CFG.SPEED_LIMIT>3) CFG.SPEED_LIMIT=3; if (CFG.SPEED_LIMIT<1) CFG.SPEED_LIMIT=1; if (CFG.WITHOUT_FACE==0) set_speed_buttons(); }; void tMain::check_for_remote_commands(){ int i=0; while (!server->empty()){ d4x::RemoteCommand addnew=server->get_command(); switch (addnew.type){ case PACKET_RERUN_FAILED:{ MainLog->myprintf(LOG_FROM_SERVER|LOG_DETAILED,"%s %s",_("Restarting failed downloads"),_("[control socket]")); rerun_failed(); break; }; case PACKET_OPENLIST:{ create_addlinks_with_referer(addnew.params,CFG.LOCAL_SAVE_PATH); break; }; case PACKET_ADD_OPEN:{ if (CFG.WITHOUT_FACE==0){ if (addnew.params.size()>1) init_add_dnd_window(addnew.params[0].c_str(),NULL,addnew.params[1].c_str()); else init_add_dnd_window(addnew.params[0].c_str(),NULL); }; break; }; case PACKET_STOP:{ // MainLog->myprintf(LOG_FROM_SERVER,_("Stop the download via control socket [%s]"),addnew.params[0].c_str()); stop_download_url(d4x::URL(addnew.params[0])); break; }; case PACKET_DEL:{ MainLog->myprintf(LOG_FROM_SERVER,_("Remove the download via control socket [%s]"),addnew.params[0].c_str()); delete_download_url(d4x::URL(addnew.params[0])); break; }; case PACKET_ADD:{ TO_WAIT_IF_HERE=1; MainLog->myprintf(LOG_FROM_SERVER,_("Adding downloading via control socket [%s]"),addnew.params[0].c_str()); if (addnew.params.size()>1) add_downloading(addnew.params[0].c_str(),CFG.LOCAL_SAVE_PATH,0,0,addnew.params[1].c_str()); else add_downloading(addnew.params[0].c_str(),CFG.LOCAL_SAVE_PATH); TO_WAIT_IF_HERE=0; break; }; case PACKET_SET_SPEED_LIMIT:{ sscanf(addnew.params[0].c_str(),"%i",&CFG.SPEED_LIMIT); set_speed(CFG.SPEED_LIMIT); MainLog->myprintf(LOG_FROM_SERVER|LOG_DETAILED,_("Set speed limitation to %s %s"), _(SPEED_LIMITATIONS_NAMES[CFG.SPEED_LIMIT]), _("[control socket]")); break; }; case PACKET_SET_SAVE_PATH:{ /* to avoid misunderstandings we allow only absolute pathes here */ if (addnew.params[0].c_str() && addnew.params[0].c_str()[0]=='/'){ delete[] CFG.LOCAL_SAVE_PATH; CFG.LOCAL_SAVE_PATH=copy_string(addnew.params[0].c_str()); }; break; }; case PACKET_SET_MAX_THREADS:{ sscanf(addnew.params[0].c_str(),"%i",&(D4X_QUEUE->MAX_ACTIVE)); if (D4X_QUEUE->MAX_ACTIVE>50) D4X_QUEUE->MAX_ACTIVE=50; if (D4X_QUEUE->MAX_ACTIVE<0) D4X_QUEUE->MAX_ACTIVE=0; MainLog->myprintf(LOG_FROM_SERVER|LOG_DETAILED,"%s %i %s",_("Setup maximum active downloads to"),D4X_QUEUE->MAX_ACTIVE,_("[control socket]")); if (CFG.WITHOUT_FACE==0) D4X_QVT->update(D4X_QUEUE); break; }; case PACKET_DEL_COMPLETED:{ MainLog->myprintf(LOG_FROM_SERVER|LOG_DETAILED,"%s %s",_("Delete completed downloads"),_("[control socket]")); del_all_from_list(DL_COMPLETE); break; }; case PACKET_MSG: MainLog->myprintf(LOG_FROM_SERVER,"%s %s",addnew.params[0].c_str(),_("[control socket]")); break; case PACKET_ICONIFY: if (CFG.WITHOUT_FACE==0) main_window_iconify(); break; case PACKET_POPUP: if (CFG.WITHOUT_FACE==0) main_window_popup(); break; case PACKET_EXIT_TIME:{ int tmp; if (addnew.params[0].c_str() && sscanf(addnew.params[0].c_str(),"%d",&tmp)){ if (tmp==0){ CFG.EXIT_COMPLETE=0; MainLog->myprintf(LOG_FROM_SERVER,_("Exiting if nothing to do is switched off"),_("[control socket]")); }; if (tmp>0){ CFG.EXIT_COMPLETE=1; CFG.EXIT_COMPLETE_TIME=tmp; MainLog->myprintf(LOG_FROM_SERVER,_("Downloader will exit if nothing to do after %i minutes %s"),tmp,_("[control socket]")); }; }; break; }; case PACKET_SWITCH_QUEUE:{ int num=0; if (addnew.params[0].c_str() && sscanf(addnew.params[0].c_str(),"%d",&num)==1 && num>0){ d4xDownloadQueue *q=d4x_get_queue_num(num); if (q){ if (CFG.WITHOUT_FACE==0){ D4X_QVT->switch_remote(q); }else{ MainLog->myprintf(LOG_FROM_SERVER,_("Default queue is '%s' now."),q->name.get()); D4X_QUEUE=q; }; }; }; break; }; }; i+=1; if (i>10) break; }; }; //**********************************************/ void tMain::ftp_search(tDownload *what,int type){ DBC_RETURN_IF_FAIL(what!=NULL); if (!what->info.file.empty()){ tDownload *tmp=new tDownload; tmp->config=new tCfg; tmp->fsearch=type; tmp->set_default_cfg(); tmp->info=what->info; tmp->finfo.size=what->finfo.size; tmp->info.proto=D_PROTO_SEARCH; if (tmp->split){ delete(tmp->split); tmp->split=NULL; }; ftpsearch->add(tmp); }; }; void tMain::ftp_search_name(char *name){ if (name){ tDownload *tmp=new tDownload; tmp->config=new tCfg; tmp->fsearch=0; tmp->set_default_cfg(); tmp->info.file=name; tmp->finfo.size=-1; tmp->info.proto=D_PROTO_SEARCH; if (tmp->split){ delete(tmp->split); tmp->split=NULL; }; ftpsearch->add(tmp); }; }; void tMain::ftp_search_reping(tDownload *what){ if (ftpsearch) ftpsearch->reping(what); }; void tMain::ftp_search_remove(tDownload *what){ if (ftpsearch) ftpsearch->remove(what); }; void tMain::schedule_download(tDownload *what){ if (what->owner()==DL_RUN || what->owner()==DL_STOPWAIT) return; DQV(what).remove(what); ALL_DOWNLOADS->del(what); what->myowner->PAPA->del(what); if (what->LOG){ delete(what->LOG); what->LOG=NULL; }; if (what->split){ delete(what->split); what->split=NULL; }; MainScheduler->add_scheduled(what); }; void tMain::sizequery_run_first(d4xDownloadQueue *q){ tDownload *torun=q->first(DL_SIZEQUERY); if (torun){ if (torun->config==NULL){ torun->config=new tCfg; torun->set_default_cfg(); }; if (torun->split) torun->split->grandparent=torun; run_new_thread(torun); }; }; void tMain::move_to_sizequery(tDownload *what){ if (CFG.OFFLINE_MODE) return; if (what==NULL) return; if (what->owner()==DL_STOPWAIT){ what->action=ACTION_SIZEQUERY; return; }; int owner=what->owner(); if (owner!=DL_SIZEQUERY && owner!=DL_RUN){ d4xDownloadQueue *papa=what->myowner->PAPA; what->action=owner; papa->del(what); papa->add(what,DL_SIZEQUERY); what->sizequery=1; if (papa->count(DL_SIZEQUERY)==1) sizequery_run_first(papa); }; }; tDownload *tMain::add_downloading(tDownload *what,int to_top) { tDownload *tdwn=NULL; if ((tdwn=ALL_DOWNLOADS->find(what)) || !what->info.is_valid()) { printf("%s\n",std::string(what->info).c_str()); if (TO_WAIT_IF_HERE && tdwn && tdwn->owner()!=DL_RUN){ continue_download(tdwn); }; return(tdwn); }; if (what->ScheduleTime){ MainScheduler->add_scheduled(what); return(NULL); }; if (what->config==NULL){ FaceForPasswords->set_cfg(what); }; ALL_DOWNLOADS->insert(what); tDownload *f=D4X_QUEUE->first(DL_WAIT); if (to_top && f) D4X_QUEUE->insert_before(what,f); else D4X_QUEUE->add(what); if (to_top) D4X_QUEUE->qv.add_first(what); else D4X_QUEUE->qv.add(what); try_to_run_wait(D4X_QUEUE); return(NULL); }; tDownload *tMain::add_downloading_to(tDownload *what,int to_top) { DBC_RETVAL_IF_FAIL(what!=NULL,NULL); int owner=what->status; if (what->ScheduleTime){ MainScheduler->add_scheduled(what); return NULL; }; if (owner>DL_ALONE && ownerfind(what); // if (dwn && CFG.WITHOUT_FACE==0 && CFG.NEED_DIALOG_FOR_DND==0){ // D4X_QVT->move_to(dwn); // }; delete (what); DONTRY2RUN=0;; return dwn; }; switch(owner){ case DL_RUN:{ if (try_to_run_download(what)){ D4X_QUEUE->del(what); D4X_QUEUE->add(what,DL_RUN); }; break; }; case DL_STOPWAIT: case DL_STOP:{ D4X_QUEUE->del(what); D4X_QUEUE->add(what,DL_STOP); break; }; case DL_COMPLETE:{ D4X_QUEUE->del(what); D4X_QUEUE->add(what,DL_COMPLETE); break; }; case DL_PAUSE:{ D4X_QUEUE->del(what); D4X_QUEUE->add(what,DL_PAUSE); break; }; }; DONTRY2RUN=0; try_to_run_wait(D4X_QUEUE); }else{ delete(what); }; return(NULL); }; int tMain::add_downloading(const char *adr,char *where,char *name,char *desc,const char *referer) { if (adr==NULL) return -1; // if (!addr->is_valid()) return -1; tDownload *whatadd=new tDownload; whatadd->info=std::string(adr); if (where && *where) { whatadd->config=new tCfg; whatadd->set_default_cfg(); whatadd->config->save_path.set(where); whatadd->config->isdefault=0; }; if (referer && *referer){ if (whatadd->config==0){ whatadd->config=new tCfg; whatadd->set_default_cfg(); whatadd->config->isdefault=0; }; whatadd->config->referer.set(referer); }; if (whatadd->info.file.empty()) { whatadd->finfo.type=T_DIR; whatadd->finfo.size=0; }; // normalize_path(whatadd->get_SavePath()); if (name && strlen(name) && whatadd->config){ whatadd->Name2Save=name; }; whatadd->Description.set(desc); if (add_downloading(whatadd)) { delete(whatadd); return -1; }; return 0; }; unsigned int tMain::get_precise_time(){ #if (defined(BSD) && (BSD >= 199306)) struct timeval tp; gettimeofday(&tp, NULL); return(tp.tv_sec*1000+tp.tv_usec/1000); #else struct timeb tp; ftime(&tp); return(tp.time*1000+tp.millitm); #endif }; void tMain::speed() { unsigned int curent_time=get_precise_time(); unsigned int TimeLeft=curent_time-LastTime; tMeter::BSize readed_bytes=GVARS.READED_BYTES; tMeter::BSize bytes=readed_bytes-LastReadedBytes; if (TimeLeft!=0){ int Speed=((bytes*1000)/TimeLeft); LastReadedBytes=readed_bytes; GlobalMeter->add(Speed); GraphMeter->add(Speed); LastTime=curent_time; }; int SPEED_LIMIT=0; switch (CFG.SPEED_LIMIT) { case 1: { SPEED_LIMIT=(TimeLeft*CFG.SPEED_LIMIT_1)/1000; break; }; case 2: { SPEED_LIMIT=(TimeLeft*CFG.SPEED_LIMIT_2)/1000; break; }; case 3: default:{ SPEED_LIMIT=0; }; }; if (SPEED_LIMIT){ // SPEED_LIMIT+=(prev_speed_limit-bytes)/2; if (SPEED_LIMIT>0) SpeedScheduler->schedule(SPEED_LIMIT,1); }else SpeedScheduler->schedule(TimeLeft); prev_speed_limit=SPEED_LIMIT; }; void tMain::run(int argv,char **argc) { SOUND_SERVER->run_thread(); if (CFG.WITHOUT_FACE==0){ if (CFG.USE_THEME && CFG.THEME_FILE){ char *tmp=sum_strings(CFG.THEMES_DIR,"/",CFG.THEME_FILE,".xml",NULL); D4X_THEME_DATA=d4x_xml_parse_file(tmp); delete[] tmp; }; ftpsearch=new tFtpSearchCtrl; init_face(argv,argc); ftpsearch->init(FSearchView,this,MainLog); fs_list_set_size(); }; init_main_log(); MainLog->add(VERSION_NAME,LOG_WARNING); COOKIES=new tCookiesTree; COOKIES->load_cookies(); load_defaults(); if (CFG.WITHOUT_FACE==0){ prepare_buttons(); init_timeouts(); }; parse_command_line_postload(argv,argc); server->run_thread(); LastTime=get_precise_time(); var_check_all_limits(); MainLog->add(_("Loading FTP-Search engines"),LOG_WARNING); D4X_SEARCH_ENGINES.load(); MainLog->add(_("Normally started"),LOG_WARNING); check_for_remote_commands(); GlobalMeter->set_mode(CFG.GRAPH_MODE); GraphMeter->set_mode(CFG.GRAPH_MODE); MainScheduler->clear_old(); if (CFG.WITHOUT_FACE==0){ SOUND_SERVER->add_event(SND_STARTUP); gtk_main(); }else{ run_without_face(); }; }; void tMain::run_without_face(){ int TIME_FOR_SAVING=CFG.SAVE_LIST_INTERVAL * 60; int COMPLETE_INTERVAL=CFG.EXIT_COMPLETE_TIME * 60; struct timespec ival={0,200000000}; int i=0; while(1){ check_for_remote_commands(); main_circle_nano2(); if (i++>=5){ main_circle(); i=0; }; nanosleep(&ival,NULL); // sleep(1); TIME_FOR_SAVING-=1; if (!TIME_FOR_SAVING) { if (CFG.SAVE_LIST) { save_list(); }; TIME_FOR_SAVING=CFG.SAVE_LIST_INTERVAL * 60; }; if (CFG.EXIT_COMPLETE && d4x_run_or_wait_downloads()==0){ COMPLETE_INTERVAL-=1; if (COMPLETE_INTERVAL<0){ break; }; }else{ COMPLETE_INTERVAL=CFG.EXIT_COMPLETE_TIME * 60; }; }; save_list(); done(); save_config(); for (int i=0;iinfo.file); MainLog->myprintf(LOG_OK,_("Added downloading of file %s from %s [by user]"),rfile.c_str(),what->info.host.c_str()); }; static int not_all_stopped(tQueue *q){ d4xDownloadQueue *dq=(d4xDownloadQueue *)q->first(); while(dq){ if (dq->count(DL_STOPWAIT)) return(1); if (not_all_stopped(&(dq->child))) return(1); dq=(d4xDownloadQueue *)(dq->prev); }; return(0); }; void tMain::stop_all(tQueue *q){ d4xDownloadQueue *dq=(d4xDownloadQueue *)q->first(); while(dq){ stop_all(&(dq->child)); tDownload *d=dq->first(DL_RUN); while (d){ stop_download(d); d=dq->first(DL_RUN); } dq=(d4xDownloadQueue *)(dq->prev); }; }; void tMain::stop_all_offline(tQueue *q){ d4xDownloadQueue *dq=(d4xDownloadQueue *)q->first(); while(dq){ stop_all_offline(&(dq->child)); tDownload *d=dq->first(DL_RUN); while (d){ stop_download(d); d->action=ACTION_CONTINUE; d=dq->first(DL_RUN); } d=dq->first(DL_SIZEQUERY); if (d) stop_download(d); dq=(d4xDownloadQueue *)(dq->prev); }; }; void tMain::switch_offline_mode(){ if (CFG.OFFLINE_MODE==0){ CFG.OFFLINE_MODE=1; stop_all_offline(&D4X_QTREE); ftpsearch->stop_all_offline(); MainLog->add(_("Downloader is in offline mode now"),LOG_WARNING|LOG_DETAILED); }else{ CFG.OFFLINE_MODE=0; int tmpfr=CFG.ALLOW_FORCE_RUN; CFG.ALLOW_FORCE_RUN=1; main_circle_nano2(); CFG.ALLOW_FORCE_RUN=tmpfr; MainLog->add(_("Offline mode is turned off"),LOG_WARNING|LOG_DETAILED); }; if (!CFG.WITHOUT_FACE){ d4x_main_offline_mode(); }; }; void tMain::done() { /* There are we MUST stop all threads!!! */ server->stop_thread(); /* removing ftpsearch before removing all queues to avoid segfault at host-limit checks */ if (ftpsearch) delete(ftpsearch); FaceForPasswords->save(); if (FaceForPasswords) delete (FaceForPasswords); stop_all(&D4X_QTREE); while(not_all_stopped(&D4X_QTREE)){ main_circle_nano2(); sleep(1); }; D4X_QUEUE->done(); MainScheduler->save(); delete(MainScheduler); delete(GlobalMeter); delete(GraphMeter); delete(GraphLMeter); delete(LocalMeter); delete(ALL_DOWNLOADS); // delete or not delete that is the question :-) COOKIES->save_cookies(); delete(COOKIES); MainLog->init_list(NULL); MainLog->myprintf(LOG_OK,_("%lu bytes loaded during the session"),GVARS.READED_BYTES); MainLog->add(_("Downloader exited normaly"),LOG_OK); delete(MainLog); delete(SpeedScheduler); close(LOCK_FILE_D); delete (server); delete (MsgQueue); /* for (int i=URL_HISTORY;istop_thread(); delete(SOUND_SERVER); delete(GVARS.SOCKETS); if (D4X_THEME_DATA) delete(D4X_THEME_DATA); if (LOCK_FILE) remove(LOCK_FILE); if (D4X_QVT) delete(D4X_QVT); }; void tMain::reinit_main_log() { MainLog->reinit(CFG.MAX_MAIN_LOG_LENGTH); MainLog->reinit_file(); }; //*****************************************************************/ //----------------------------------------------------------------- void *download_last(void *nothing) { tDownload *what=(tDownload *)nothing; my_pthread_key_init(); my_pthread_key_set(what); init_signal_handler(); if (what) { d4x::URL *addr=&(what->info); what->LOG->MsgQueue=LogsMsgQueue; if (what->config->log_save_path.get()){ char *real_path=parse_save_path(what->config->log_save_path.get(),what->info.file.c_str()); make_dir_hier_without_last(real_path); if (what->LOG->init_save(real_path)){ what->WL->log_printf(LOG_ERROR, _("Can't open '%s' to save log"), real_path); }; delete[] real_path; }else{ what->LOG->init_save(NULL); }; if ((what->config->proxy.http_host.get() && addr->proto==D_PROTO_HTTP) || (what->config->proxy.ftp_host.get() && addr->proto==D_PROTO_FTP && what->config->proxy.type)) { what->who=new tProxyDownload(what->WL); what->download_http(); pthread_exit(NULL); return NULL; }; switch(addr->proto){ case D_PROTO_SEARCH: if (what->who==NULL){ if (what->config->proxy.http_host.get()) what->who=new tProxyDownload(what->WL); else what->who=new tHttpDownload(what->WL); }; what->ftp_search(); break; #ifdef HAVE_SSL case D_PROTO_HTTPS: #endif //HAVE_SSL case D_PROTO_HTTP: what->download_http(); break; case D_PROTO_FTP: what->download_ftp(); break; default: what->WL->log(LOG_ERROR,_("Such protocol is not supported!")); what->download_failed(); break; }; }; pthread_exit(NULL); return NULL; }; //------------------------------------------------------------------------