Kazuhiro NISHIYAMA
zn****@mbf*****
2005年 2月 24日 (木) 18:41:55 JST
西山和広です。 Content-Encoding: x-gzip 対応をしてみたのですが、強制的に buffer modeにする方法がわからなかったので、リモートブックマークの x-gzipは対処できたのですが、ドロップしてダウンロードでは CRITICAL **: kz_io_decode_buffer: assertion `kz_io_is_buffer_mode(io)' failed と出て、gzipされたままダウンロードされます。 これで、samidareのsites.lirs.gzが使えるようになります。 ただしgzipの入力に一時ファイルを使って出力はg_spawn_syncに まかせてgchar**で受け取るようにしてしまったので、'\0'が入る バイナリやUTF-8以外のUnicodeなどで問題がありそうです。 それに対処しようかと思ってContent-Typeも保存するようにして みたのですが、textの時だけデコードするようにしても結局 Unicodeで問題がありそうなので、Content-Typeは使っていません。 以上のような状況なのですが、commitしてしまっても良いでしょうか? g_spawn_async_with_pipesを使うか何かで'\0'対策をしておかないと だめでしょうか? -- |ZnZ(ゼット エヌ ゼット) |西山和広(Kazuhiro NISHIYAMA) -------------- next part -------------- Index: src/net/kz-http.c =================================================================== RCS file: /cvsroot/kazehakase/kazehakase/src/net/kz-http.c,v retrieving revision 1.54 diff -u -p -r1.54 kz-http.c --- src/net/kz-http.c 24 Feb 2005 03:33:55 -0000 1.54 +++ src/net/kz-http.c 24 Feb 2005 08:54:46 -0000 @@ -25,6 +25,7 @@ #define __USE_XOPEN #include <time.h> #include <glib/gi18n.h> +#include <unistd.h> #include "gobject-utils.h" #include "kz-http.h" @@ -70,6 +71,8 @@ struct _KzHTTPPrivate gboolean redirection; /* for Redirection 3xx */ gchar *location; /* Redirect-URI */ + gchar *content_type; + gchar *content_encoding; gchar *post_data; }; @@ -208,6 +211,8 @@ kz_http_init (KzHTTP *http) http->priv->chunked = FALSE; http->priv->redirection = FALSE; http->priv->location = NULL; + http->priv->content_type = NULL; + http->priv->content_encoding = NULL; http->priv->chunk_size = 0; @@ -230,6 +235,10 @@ kz_http_dispose (GObject *object) g_free(http->priv->path); if (http->priv->location) g_free(http->priv->location); + if (http->priv->content_type) + g_free(http->priv->content_type); + if (http->priv->content_encoding) + g_free(http->priv->content_encoding); if (http->priv->post_data) g_free(http->priv->post_data); @@ -237,6 +246,8 @@ kz_http_dispose (GObject *object) http->priv->hostname = NULL; http->priv->path = NULL; http->priv->location = NULL; + http->priv->content_type = NULL; + http->priv->content_encoding = NULL; http->priv->post_data = NULL; if (G_OBJECT_CLASS (parent_class)->dispose) @@ -411,6 +422,20 @@ kz_http_in_header(KzHTTP *http, GIOChann if (g_str_has_prefix(value, "chunked")) kz_http_set_chunked_mode(http); } + else if (g_ascii_strncasecmp(buffer->str, "Content-Type:", 13) == 0) + { + const gchar *value = buffer->str + 13; + while (*value && g_ascii_isspace(*value)) + ++value; + http->priv->content_type = g_strchomp(g_strdup(value)); + } + else if (g_ascii_strncasecmp(buffer->str, "Content-Encoding:", 17) == 0) + { + const gchar *value = buffer->str + 17; + while (*value && g_ascii_isspace(*value)) + ++value; + http->priv->content_encoding = g_strchomp(g_strdup(value)); + } else if (g_ascii_strncasecmp(buffer->str, "Location:", 9) == 0) { const gchar *value = buffer->str + 9; @@ -549,11 +574,17 @@ kz_http_read_from_io (KzIO *io, GIOChann else /* Entity-Body Section */ iostatus = kz_http_in_body(http, iochannel); - if (iostatus == G_IO_STATUS_EOF && kz_http_is_redirection(http)) - { - g_object_set(G_OBJECT(http), - "uri", g_strchomp(http->priv->location), NULL); - iostatus = G_IO_STATUS_AGAIN; + if (iostatus == G_IO_STATUS_EOF) { + if (kz_http_is_redirection(http)) + { + g_object_set(G_OBJECT(http), + "uri", g_strchomp(http->priv->location), + NULL); + iostatus = G_IO_STATUS_AGAIN; + } + else if (http->priv->content_encoding) { + return kz_io_decode_buffer(KZ_IO(http), http->priv->content_encoding); + } } return iostatus; Index: src/net/kz-io.c =================================================================== RCS file: /cvsroot/kazehakase/kazehakase/src/net/kz-io.c,v retrieving revision 1.31 diff -u -p -r1.31 kz-io.c --- src/net/kz-io.c 13 Feb 2005 22:55:15 -0000 1.31 +++ src/net/kz-io.c 24 Feb 2005 08:54:46 -0000 @@ -733,3 +733,83 @@ kz_io_stop (KzIO *io) return; } + +#include <sys/wait.h> +#include <unistd.h> + +static void +kz_io_decode_child_setup(gpointer user_data) +{ + GString *string = user_data; + gchar *name_used = NULL; + GError *error = NULL; + gint fd = g_file_open_tmp("kz_io_decode.XXXXXX", &name_used, &error); + if (name_used) { + unlink(name_used); + g_free(name_used); + name_used = NULL; + } + + if (error) { + g_warning("g_file_open_tmp: %s", error->message); + g_error_free(error); + return; + } + + write(fd, string->str, string->len); + lseek(fd, 0, SEEK_SET); + + dup2(fd, 0); + close(fd); +} + +GIOStatus +kz_io_decode_buffer(KzIO *io, const gchar *content_encoding) +{ + GIOStatus status = G_IO_STATUS_EOF; + GError *error = NULL; + gchar *standard_output = NULL; + gint exit_status = 0; + gboolean success; + + g_return_val_if_fail(KZ_IS_IO(io), status); + g_return_val_if_fail(kz_io_is_buffer_mode(io), status); + g_return_val_if_fail(content_encoding, status); + + if (strcmp(content_encoding, "x-gzip") == 0) { + gchar *argv[] = { + "gzip", "-dc", NULL, + }; + GString *string = g_string_new_len( + kz_io_get_buffer(io), + kz_io_get_loaded_size(io)); + success = g_spawn_sync(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, + kz_io_decode_child_setup, string, + &standard_output, NULL, &exit_status, + &error); + g_string_free(string, TRUE); + } else { + return status; + } + if (error) { + g_warning("g_spawn_sync failed: %s", error->message); + g_error_free(error); + } else if (!success) { + g_warning("g_spawn_sync failed"); + } else if (exit_status != 0 || standard_output == NULL) { + g_warning("decode content failed: status=%d", exit_status); + g_warning("WIFEXITED=%d WEXITSTATUS=%d", WIFEXITED(exit_status), WEXITSTATUS(exit_status)); + g_warning("WIFSIGNALED=%d WTERMSIG=%d", WIFSIGNALED(exit_status), WTERMSIG(exit_status)); + g_warning("WIFSTOPPED=%d WSTOPSIG=%d", WIFSTOPPED(exit_status), WSTOPSIG(exit_status)); + } else { + /* reset buffer */ + gsize len = strlen(standard_output); + g_string_truncate(io->priv->buffer, 0); + io->priv->loaded_size = 0; + io->priv->file_size = len; + io_to_buffer(io, len, standard_output); + } + g_free(standard_output); + + return status; +} Index: src/net/kz-io.h =================================================================== RCS file: /cvsroot/kazehakase/kazehakase/src/net/kz-io.h,v retrieving revision 1.14 diff -u -p -r1.14 kz-io.h --- src/net/kz-io.h 25 Nov 2004 07:28:48 -0000 1.14 +++ src/net/kz-io.h 24 Feb 2005 08:54:46 -0000 @@ -96,6 +96,8 @@ const gchar *kz_io_get_buffer (KzI void kz_io_start (KzIO *io); void kz_io_stop (KzIO *io); KzIOMode kz_io_get_mode (KzIO *io); +GIOStatus kz_io_decode_buffer (KzIO *io, + const gchar *content_encoding); G_END_DECLS