/* Standard HTTP proxy port */
#define DEFAULT_HTTP_PROXY_PORT 8080
+/* Maximum amount of data to read if seek()ed forward. Otherwise make a new connection. */
+#define MAX_BUFFER_SEEK_SKIP_READ 0x10000
+
/* GConf paths and keys */
#define PATH_GCONF_GNOME_VFS "/system/http_proxy"
#define ITEM_GCONF_HTTP_PROXY_PORT "port"
/* File info for this file */
GnomeVFSFileInfo *file_info;
- /* Bytes read so far. */
- GnomeVFSFileSize bytes_read;
+ /* File offset of current pointer of 'socket_buffer'. */
+ GnomeVFSFileOffset socket_buffer_offset;
+
+ /* Offset; Current file position. */
+ GnomeVFSFileOffset offset;
/* Bytes to be written... */
GByteArray *to_be_written;
} else {
result = GNOME_VFS_OK;
}
-
+
http_handle_close (old_handle, context);
g_free (old_handle);
GnomeVFSMethodHandle *method_handle,
gconstpointer buffer,
GnomeVFSFileSize num_bytes,
- GnomeVFSFileSize *bytes_read,
+ GnomeVFSFileSize *bytes_written,
GnomeVFSContext *context)
{
HttpFileHandle *handle;
handle = (HttpFileHandle *) method_handle;
+ if (handle->offset != 0)
+ return GNOME_VFS_ERROR_NOT_SUPPORTED;
+
if(handle->to_be_written == NULL) {
handle->to_be_written = g_byte_array_new();
}
handle->to_be_written = g_byte_array_append(handle->to_be_written, buffer, num_bytes);
- *bytes_read = num_bytes;
+ *bytes_written = num_bytes;
DEBUG_HTTP (("-Write (0)"));
if (handle->file_info->flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
GnomeVFSFileSize max_bytes;
- max_bytes = handle->file_info->size - handle->bytes_read;
+ max_bytes = MAX (0, handle->file_info->size - handle->offset);
num_bytes = MIN (max_bytes, num_bytes);
}
+ if (!num_bytes) {
+ *bytes_read = 0;
+ return GNOME_VFS_OK;
+ }
+
+ if (1
+ && handle->offset > handle->socket_buffer_offset
+ && handle->offset <= handle->socket_buffer_offset+MAX_BUFFER_SEEK_SKIP_READ) {
+static char drop_buffer[0x1000];
+GnomeVFSFileSize bytes, bytes_read;
+GnomeVFSResult result;
+
+ while ((bytes=MIN(sizeof(drop_buffer), handle->offset - handle->socket_buffer_offset))) {
+ result = gnome_vfs_socket_buffer_read (handle->socket_buffer, drop_buffer,
+ bytes, &bytes_read);
+ if (result != GNOME_VFS_OK)
+ return result;
+ handle->socket_buffer_offset += bytes_read;
+ }
+ }
+
+ if (handle->offset != handle->socket_buffer_offset) {
+ GnomeVFSURI *uri = handle->uri;
+ gchar *extra_headers;
+
+ gnome_vfs_uri_ref(uri);
+ http_handle_close (handle, context);
+ extra_headers = g_strdup_printf("Range: bytes=%" G_GINT64_FORMAT "-\r\n",(gint64)handle->offset);
+ result = make_request (handle, uri, "GET", NULL, extra_headers,
+ context);
+ g_free (extra_headers);
+ gnome_vfs_uri_unref(uri);
+ if (result != GNOME_VFS_OK) {
+ /* FIXME: 'method_handle' is now broken! */
+ memset(handle, 0, sizeof (*handle));
+ return result;
+ }
+ handle->socket_buffer_offset = handle->offset;
+ }
+
result = gnome_vfs_socket_buffer_read (handle->socket_buffer, buffer,
num_bytes, bytes_read);
return GNOME_VFS_ERROR_EOF;
}
- handle->bytes_read += *bytes_read;
+ handle->socket_buffer_offset += *bytes_read;
+ handle->offset += *bytes_read;
DEBUG_HTTP (("-Read (%d)", result));
ANALYZE_HTTP ("==> -do_read");
return result;
}
+static GnomeVFSResult
+do_seek (GnomeVFSMethod *method,
+ GnomeVFSMethodHandle *method_handle,
+ GnomeVFSSeekPosition whence,
+ GnomeVFSFileOffset offset,
+ GnomeVFSContext *context)
+{
+ HttpFileHandle *handle;
+
+ handle = (HttpFileHandle *) method_handle;
+
+ if (handle->to_be_written != NULL)
+ return GNOME_VFS_ERROR_NOT_SUPPORTED;
+
+ switch (whence) {
+ case GNOME_VFS_SEEK_START:
+ handle->offset = offset;
+ break;
+ case GNOME_VFS_SEEK_CURRENT:
+ handle->offset += offset;
+ break;
+ case GNOME_VFS_SEEK_END:
+ if (!(handle->file_info->flags & GNOME_VFS_FILE_INFO_FIELDS_SIZE))
+ return GNOME_VFS_ERROR_NOT_SUPPORTED;
+ handle->offset = handle->file_info->size + offset;
+ break;
+ default:
+ g_return_val_if_reached(GNOME_VFS_ERROR_NOT_SUPPORTED);
+ }
+
+ return GNOME_VFS_OK;
+}
+
+static GnomeVFSResult
+do_tell (GnomeVFSMethod *method,
+ GnomeVFSMethodHandle *method_handle,
+ GnomeVFSFileOffset *offset_return)
+{
+ HttpFileHandle *handle;
+
+ handle = (HttpFileHandle *) method_handle;
+
+ *offset_return = handle->offset;
+
+ return GNOME_VFS_OK;
+}
+
/* Directory handling - WebDAV servers only */
static void
do_close,
do_read,
do_write,
- NULL, /* seek */
- NULL, /* tell */
+ do_seek,
+ do_tell,
NULL, /* truncate_handle */
do_open_directory,
do_close_directory,