Beispiel #1
0
/**
 * Callback for low-level cache events
 *
 * \param handle  Low-level cache handle
 * \param event   Event object
 * \param pw      Our context
 * \return NSERROR_OK on success, appropriate error otherwise
 */
static nserror download_callback(llcache_handle *handle,
		const llcache_event *event, void *pw)
{
	download_context *ctx = pw;
	nserror error = NSERROR_OK;

	switch (event->type) {
	case LLCACHE_EVENT_HAD_HEADERS:
		error = download_context_process_headers(ctx);
		if (error != NSERROR_OK) {
			llcache_handle_abort(handle);
			download_context_destroy(ctx);
		}

		break;

	case LLCACHE_EVENT_HAD_DATA:
		/* If we didn't know up-front that this fetch was for download,
		 * then we won't receive the HAD_HEADERS event. Catch up now.
		 */
		if (ctx->window == NULL) {
			error = download_context_process_headers(ctx);
			if (error != NSERROR_OK) {
				llcache_handle_abort(handle);
				download_context_destroy(ctx);
			}
		}

		if (error == NSERROR_OK) {
			/** \todo Lose ugly cast */
			error = gui_download_window_data(ctx->window,
					(char *) event->data.data.buf,
					event->data.data.len);
			if (error != NSERROR_OK)
				llcache_handle_abort(handle);
		}

		break;

	case LLCACHE_EVENT_DONE:
		assert(ctx->window != NULL);

		gui_download_window_done(ctx->window);

		break;

	case LLCACHE_EVENT_ERROR:
		if (ctx->window != NULL)
			gui_download_window_error(ctx->window, event->data.msg);

		break;

	case LLCACHE_EVENT_PROGRESS:
		break;
	}

	return error;
}
Beispiel #2
0
nserror gui_download_window_data(struct gui_download_window *dw,
		const char *data, unsigned int size)
{
	while (true) {
		const char *msg;
		int unwritten;
		os_error *error;

		error = xosgbpb_writew(dw->file, (const byte *) data, size,
				&unwritten);
		if (error) {
			LOG(("xosgbpb_writew: 0x%x: %s",
					error->errnum, error->errmess));
			msg = error->errmess;

		} else if (unwritten) {
			LOG(("xosgbpb_writew: unwritten %i", unwritten));
			msg = messages_get("Unwritten");
		}
		else {
			dw->received += size;
			return NSERROR_OK;
		}

		warn_user("SaveError", msg);

		if (dw->saved) {
			/* try to continue with the temporary file */
			const char *temp_name = ro_gui_download_temp_name(dw);

			error = ro_gui_download_move(dw, temp_name, dw->path);
			if (!error) {

				/* re-allow saving */
				dw->saved = false;

				error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
						wimp_ICON_SHADED, 0);
				if (error) {
					LOG(("xwimp_set_icon_state: 0x%x: %s",
							error->errnum, error->errmess));
					warn_user("WimpError", error->errmess);
				}

				error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_DESTINATION,
						wimp_ICON_DELETED, wimp_ICON_DELETED);
				if (error) {
					LOG(("xwimp_set_icon_state: 0x%x: %s",
							error->errnum, error->errmess));
					warn_user("WimpError", error->errmess);
				}
				error = xwimp_set_icon_state(dw->window,
						ICON_DOWNLOAD_PATH, wimp_ICON_DELETED, 0);
				if (error) {
					LOG(("xwimp_set_icon_state: 0x%x: %s",
							error->errnum, error->errmess));
					warn_user("WimpError", error->errmess);
				}

				continue;
			}
		}

		/* give up then */
		assert(dw->ctx);
		download_context_abort(dw->ctx);
		gui_download_window_error(dw, msg);

		return NSERROR_SAVE_FAILED;
	}
}
Beispiel #3
0
bool ro_gui_download_save(struct gui_download_window *dw,
		const char *file_name, bool force_overwrite)
{
	fileswitch_object_type obj_type;
	const char *temp_name;
	os_error *error;

	if (dw->saved || dw->error)
		return true;

	temp_name = ro_gui_download_temp_name(dw);

	/* does the user want to check for collisions when saving? */
	if (!force_overwrite) {
		/* check whether the destination file/dir already exists */
		error = xosfile_read_stamped(file_name, &obj_type,
				NULL, NULL, NULL, NULL, NULL);
		if (error) {
			LOG(("xosfile_read_stamped: 0x%x:%s", error->errnum, error->errmess));
			return false;
		}

		switch (obj_type) {
			case osfile_NOT_FOUND:
				break;

			case osfile_IS_FILE:
				dw->query = query_user("OverwriteFile", NULL, &overwrite_funcs, dw,
							messages_get("Replace"), messages_get("DontReplace"));
				dw->query_rsn = QueryRsn_Overwrite;
				return false;

			default:
				error = xosfile_make_error(file_name, obj_type);
				assert(error);
				warn_user("SaveError", error->errmess);
				return false;
		}
	}

	if (!ro_gui_download_check_space(dw, file_name, temp_name)) {
		warn_user("SaveError", messages_get("NoDiscSpace"));
		return false;
	}

	error = ro_gui_download_move(dw, file_name, temp_name);
	if (error) {
		warn_user("SaveError", error->errmess);

		/* try to reopen at old location so that the download can continue
		   to the temporary file */
		error = xosfind_openupw(osfind_NO_PATH | osfind_ERROR_IF_DIR,
				temp_name, 0, &dw->file);
		if (error) {
			LOG(("xosfind_openupw: 0x%x: %s",
					error->errnum, error->errmess));

		} else {
			error = xosargs_set_ptrw(dw->file, dw->received);
			if (error) {
				LOG(("xosargs_set_ptrw: 0x%x: %s",
						error->errnum, error->errmess));
			}
		}

		if (error) {
			if (dw->ctx)
				download_context_abort(dw->ctx);
			gui_download_window_error(dw, error->errmess);
		}
		return false;
	}

	dw->saved = true;
	strncpy(dw->path, file_name, sizeof dw->path);

	if (!dw->send_dataload || dw->save_message.data.data_xfer.est_size != -1)
		ro_gui_download_remember_dir(file_name);

	/* grey out file icon */
	error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_ICON,
			wimp_ICON_SHADED, wimp_ICON_SHADED);
	if (error) {
		LOG(("xwimp_set_icon_state: 0x%x: %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}

	/* hide writeable path icon and show destination icon
	   Note: must redraw icon bounding box because the destination icon
		has rounded edges on RISC OS Select/Adjust and doesn't
		completely cover the writeable icon */

	ro_gui_force_redraw_icon(dw->window, ICON_DOWNLOAD_PATH);
	error = xwimp_set_icon_state(dw->window, ICON_DOWNLOAD_PATH,
			wimp_ICON_DELETED, wimp_ICON_DELETED);
	if (error) {
		LOG(("xwimp_set_icon_state: 0x%x: %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}
	error = xwimp_set_icon_state(dw->window,
			ICON_DOWNLOAD_DESTINATION, wimp_ICON_DELETED, 0);
	if (error) {
		LOG(("xwimp_set_icon_state: 0x%x: %s",
				error->errnum, error->errmess));
		warn_user("WimpError", error->errmess);
	}

	ro_gui_download_window_hide_caret(dw);

	return true;
}