/* * Copyright 2008-2010 Chris Young * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf 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; version 2 of the License. * * NetSurf 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, see . */ #include #include #include #include #include #include #include #include #ifdef __amigaos4__ #include #endif #include #include #include #include #include #include #include #include #include "utils/errors.h" #include "utils/nsurl.h" #include "utils/log.h" #include "utils/messages.h" #include "utils/utils.h" #include "utils/nsoption.h" #include "utils/string.h" #include "netsurf/browser_window.h" #include "netsurf/mouse.h" #include "netsurf/window.h" #include "netsurf/download.h" #include "content/handlers/image/ico.h" #include "desktop/download.h" #include "desktop/save_complete.h" #include "amiga/gui.h" #include "amiga/download.h" #include "amiga/object.h" #include "amiga/bitmap.h" #include "amiga/icon.h" #include "amiga/file.h" #include "amiga/iff_dr2d.h" #include "amiga/libs.h" #include "amiga/misc.h" #include "amiga/theme.h" #include "amiga/utf8.h" struct gui_download_window { struct ami_generic_window w; struct Window *win; Object *objects[GID_LAST]; BPTR fh; uint32 size; uint32 downloaded; struct dlnode *dln; struct browser_window *bw; struct download_context *ctx; const char *url; char fname[1024]; int result; }; enum { AMINS_DLOAD_OK = 0, AMINS_DLOAD_ERROR, AMINS_DLOAD_ABORT, }; static void ami_download_window_abort(void *w); static BOOL ami_download_window_event(void *w); static const struct ami_win_event_table ami_download_table = { ami_download_window_event, ami_download_window_abort, }; static int downloads_in_progress = 0; static struct gui_download_window *gui_download_window_create(download_context *ctx, struct gui_window *gui) { const char *url = nsurl_access(download_context_get_url(ctx)); unsigned long total_size = download_context_get_total_length(ctx); struct gui_download_window *dw; char *dl_filename = ami_utf8_easy(download_context_get_filename(ctx)); APTR va[3]; dw = calloc(1, sizeof(struct gui_download_window)); if(gui && (!IsListEmpty(&gui->dllist)) && (dw->dln = (struct dlnode *)FindName(&gui->dllist,url))) { strcpy(dw->fname, dw->dln->filename); free(dw->dln->node.ln_Name); dw->dln->node.ln_Name = NULL; } else { if(AslRequestTags(savereq, ASLFR_Window, gui->shared->win, ASLFR_SleepWindow, TRUE, ASLFR_TitleText, messages_get("NetSurf"), ASLFR_Screen, scrn, ASLFR_InitialFile, dl_filename, TAG_DONE)) { strlcpy(dw->fname, savereq->fr_Drawer, 1024); AddPart((STRPTR)&dw->fname,savereq->fr_File,1024); if(!ami_download_check_overwrite(dw->fname, gui->shared->win, total_size)) { free(dw); return NULL; } } else { free(dw); return NULL; } } if(dl_filename) ami_utf8_free(dl_filename); dw->size = total_size; dw->downloaded = 0; if(gui) dw->bw = gui->bw; dw->url = url; va[0] = (APTR)dw->downloaded; va[1] = (APTR)dw->size; va[2] = 0; if(!(dw->fh = FOpen((STRPTR)&dw->fname,MODE_NEWFILE,0))) { free(dw); return NULL; } dw->objects[OID_MAIN] = WindowObj, WA_ScreenTitle, ami_gui_get_screen_title(), WA_Title, dw->url, WA_Activate, TRUE, WA_DepthGadget, TRUE, WA_DragBar, TRUE, WA_CloseGadget, FALSE, WA_SizeGadget, TRUE, WA_PubScreen,scrn, WINDOW_SharedPort,sport, WINDOW_UserData,dw, WINDOW_IconifyGadget, FALSE, WINDOW_LockHeight,TRUE, WINDOW_Position, WPOS_CENTERSCREEN, WINDOW_ParentGroup, dw->objects[GID_MAIN] = LayoutVObj, LAYOUT_AddChild, dw->objects[GID_STATUS] = FuelGaugeObj, GA_ID,GID_STATUS, GA_Text,messages_get("amiDownload"), FUELGAUGE_Min,0, FUELGAUGE_Max,total_size, FUELGAUGE_Level,0, FUELGAUGE_Ticks,11, FUELGAUGE_ShortTicks,TRUE, FUELGAUGE_VarArgs,va, FUELGAUGE_Percent,FALSE, FUELGAUGE_Justification,FGJ_CENTER, FuelGaugeEnd, CHILD_NominalSize,TRUE, CHILD_WeightedHeight,0, LAYOUT_AddChild, dw->objects[GID_CANCEL] = ButtonObj, GA_ID,GID_CANCEL, GA_RelVerify,TRUE, GA_Text,messages_get("Abort"), GA_TabCycle,TRUE, ButtonEnd, EndGroup, EndWindow; dw->win = (struct Window *)RA_OpenWindow(dw->objects[OID_MAIN]); dw->ctx = ctx; ami_gui_win_list_add(dw, AMINS_DLWINDOW, &ami_download_table); downloads_in_progress++; return dw; } static nserror gui_download_window_data(struct gui_download_window *dw, const char *data, unsigned int size) { APTR va[3]; if(!dw) return NSERROR_SAVE_FAILED; FWrite(dw->fh,data,1,size); dw->downloaded = dw->downloaded + size; va[0] = (APTR)dw->downloaded; va[1] = (APTR)dw->size; va[2] = 0; if(dw->size) { RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL, FUELGAUGE_Level, dw->downloaded, GA_Text, messages_get("amiDownload"), FUELGAUGE_VarArgs, va, TAG_DONE); } else { RefreshSetGadgetAttrs((struct Gadget *)dw->objects[GID_STATUS], dw->win, NULL, FUELGAUGE_Level, dw->downloaded, GA_Text, messages_get("amiDownloadU"), FUELGAUGE_VarArgs, va, TAG_DONE); } return NSERROR_OK; } static void gui_download_window_done(struct gui_download_window *dw) { struct dlnode *dln,*dln2 = NULL; struct browser_window *bw; bool queuedl = false; if(!dw) return; bw = dw->bw; if((nsoption_bool(download_notify)) && (dw->result == AMINS_DLOAD_OK)) { Notify(ami_gui_get_app_id(), APPNOTIFY_Title, messages_get("amiDownloadComplete"), APPNOTIFY_PubScreenName, "FRONT", APPNOTIFY_BackMsg, dw->fname, APPNOTIFY_CloseOnDC, TRUE, APPNOTIFY_Text, dw->fname, TAG_DONE); } download_context_destroy(dw->ctx); if((dln = dw->dln)) { dln2 = (struct dlnode *)GetSucc((struct Node *)dln); if((dln!=dln2) && (dln2)) queuedl = true; free(dln->filename); Remove((struct Node *)dln); free(dln); } FClose(dw->fh); SetComment(dw->fname, dw->url); downloads_in_progress--; DisposeObject(dw->objects[OID_MAIN]); ami_gui_win_list_remove(dw); if(queuedl) { nsurl *url; if (nsurl_create(dln2->node.ln_Name, &url) != NSERROR_OK) { amiga_warn_user("NoMemory", 0); } else { browser_window_navigate(bw, url, NULL, BW_NAVIGATE_DOWNLOAD, NULL, NULL, NULL); nsurl_unref(url); } } ami_try_quit(); /* In case the only window open was this download */ } static void gui_download_window_error(struct gui_download_window *dw, const char *error_msg) { amiga_warn_user("Unwritten",""); dw->result = AMINS_DLOAD_ERROR; gui_download_window_done(dw); } static void ami_download_window_abort(void *w) { struct gui_download_window *dw = (struct gui_download_window *)dw; download_context_abort(dw->ctx); dw->result = AMINS_DLOAD_ABORT; gui_download_window_done(dw); } static BOOL ami_download_window_event(void *w) { /* return TRUE if window destroyed */ struct gui_download_window *dw = (struct gui_download_window *)w; ULONG result; uint16 code; while((result = RA_HandleInput(dw->objects[OID_MAIN], &code)) != WMHI_LASTMSG) { switch(result & WMHI_CLASSMASK) // class { case WMHI_GADGETUP: switch(result & WMHI_GADGETMASK) { case GID_CANCEL: ami_download_window_abort(dw); return TRUE; break; } break; } } return FALSE; } void ami_free_download_list(struct List *dllist) { struct dlnode *node; struct dlnode *nnode; if(!dllist) return; if(IsListEmpty(dllist)) return; node = (struct dlnode *)GetHead((struct List *)dllist); do { nnode=(struct dlnode *)GetSucc((struct Node *)node); free(node->node.ln_Name); free(node->filename); Remove((struct Node *)node); free((struct Node *)node); }while((node=nnode)); } nserror gui_window_save_link(struct gui_window *g, nsurl *url, const char *title) { char fname[1024]; STRPTR openurlstring,linkname; struct DiskObject *dobj = NULL; linkname = ASPrintf("Link_to_%s",FilePart(nsurl_access(url))); if(AslRequestTags(savereq, ASLFR_Window, g->shared->win, ASLFR_SleepWindow, TRUE, ASLFR_TitleText,messages_get("NetSurf"), ASLFR_Screen,scrn, ASLFR_InitialFile,linkname, TAG_DONE)) { strlcpy(fname, savereq->fr_Drawer, 1024); AddPart(fname,savereq->fr_File,1024); ami_set_pointer(g->shared, GUI_POINTER_WAIT, false); if(ami_download_check_overwrite(fname, g->shared->win, 0)) { BPTR fh; if((fh = FOpen(fname,MODE_NEWFILE,0))) { /* \todo Should be URLOpen on OS4.1 */ openurlstring = ASPrintf("openurl \"%s\"\n",nsurl_access(url)); FWrite(fh,openurlstring,1,strlen(openurlstring)); FClose(fh); FreeVec(openurlstring); SetComment(fname, nsurl_access(url)); dobj = GetIconTags(NULL,ICONGETA_GetDefaultName,"url", ICONGETA_GetDefaultType,WBPROJECT, TAG_DONE); dobj->do_DefaultTool = "IconX"; PutIconTags(fname,dobj, ICONPUTA_NotifyWorkbench,TRUE, TAG_DONE); FreeDiskObject(dobj); } FreeVec(linkname); } ami_reset_pointer(g->shared); } return NSERROR_OK; } BOOL ami_download_check_overwrite(const char *file, struct Window *win, ULONG size) { /* Return TRUE if file can be (over-)written */ int32 res = 0; BPTR lock = 0; char *overwritetext; if(nsoption_bool(ask_overwrite) == false) return TRUE; lock = Lock(file, ACCESS_READ); if(lock) { if(size) { BPTR fh; int64 oldsize = 0; if((fh = OpenFromLock(lock))) { oldsize = GetFileSize(fh); Close(fh); } overwritetext = ASPrintf("%s\n\n%s %s\n%s %s", messages_get("OverwriteFile"), messages_get("amiSizeExisting"), human_friendly_bytesize((ULONG)oldsize), messages_get("amiSizeNew"), human_friendly_bytesize(size)); } else { UnLock(lock); overwritetext = ASPrintf(messages_get("OverwriteFile")); } res = amiga_warn_user_multi(overwritetext, "Replace", "DontReplace", win); FreeVec(overwritetext); } else return TRUE; if(res == 1) return TRUE; else return FALSE; } static struct gui_download_table download_table = { .create = gui_download_window_create, .data = gui_download_window_data, .error = gui_download_window_error, .done = gui_download_window_done, }; struct gui_download_table *amiga_download_table = &download_table;