/** * Create file stream and set mime type for channel * @param info file info used to determine mime type * @return NS_OK when file stream created successfuly, error code otherwise */ nsresult nsGIOInputStream::DoOpenFile(GFileInfo *info) { GError *error = nullptr; mStream = g_file_read(mHandle, nullptr, &error); if (!mStream) { nsresult rv = MapGIOResult(error); g_warning("Cannot read from file: %s", error->message); g_error_free(error); return rv; } const char * content_type = g_file_info_get_content_type(info); if (content_type) { char *mime_type = g_content_type_get_mime_type(content_type); if (mime_type) { if (strcmp(mime_type, APPLICATION_OCTET_STREAM) != 0) { SetContentTypeOfChannel(mime_type); } g_free(mime_type); } } else { g_warning("Missing content type."); } mBytesRemaining = g_file_info_get_size(info); // Update the content length attribute on the channel. We do this // synchronously without proxying. This hack is not as bad as it looks! mChannel->SetContentLength(mBytesRemaining); return NS_OK; }
/** * Create list of infos about objects in opened directory * Return: NS_OK when list obtained, otherwise error code according * to failed operation. */ nsresult nsGIOInputStream::DoOpenDirectory() { GError *error = nullptr; GFileEnumerator *f_enum = g_file_enumerate_children(mHandle, "standard::*,time::*", G_FILE_QUERY_INFO_NONE, nullptr, &error); if (!f_enum) { nsresult rv = MapGIOResult(error); g_warning("Cannot read from directory: %s", error->message); g_error_free(error); return rv; } // fill list of file infos GFileInfo *info = g_file_enumerator_next_file(f_enum, nullptr, &error); while (info) { mDirList = g_list_append(mDirList, info); info = g_file_enumerator_next_file(f_enum, nullptr, &error); } g_object_unref(f_enum); if (error) { g_warning("Error reading directory content: %s", error->message); nsresult rv = MapGIOResult(error); g_error_free(error); return rv; } mDirOpen = true; // Sort list of file infos by using FileInfoComparator function mDirList = g_list_sort(mDirList, FileInfoComparator); mDirListPtr = mDirList; // Write base URL (make sure it ends with a '/') mDirBuf.AppendLiteral("300: "); mDirBuf.Append(mSpec); if (mSpec.get()[mSpec.Length() - 1] != '/') mDirBuf.Append('/'); mDirBuf.Append('\n'); // Write column names mDirBuf.AppendLiteral("200: filename content-length last-modified file-type\n"); // Write charset (assume UTF-8) // XXX is this correct? mDirBuf.AppendLiteral("301: UTF-8\n"); SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT); return NS_OK; }
GnomeVFSResult nsGnomeVFSInputStream::DoOpen() { GnomeVFSResult rv; NS_ASSERTION(mHandle == nsnull, "already open"); // Push a callback handler on the stack for this thread, so we can intercept // authentication requests from GnomeVFS. We'll use the channel to get a // nsIAuthPrompt instance. gnome_vfs_module_callback_push(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION, AuthCallback, mChannel, NULL); // Query the mime type first (this could return NULL). // // XXX We need to do this up-front in order to determine how to open the URI. // Unfortunately, the error code GNOME_VFS_ERROR_IS_DIRECTORY is not // always returned by gnome_vfs_open when we pass it a URI to a directory! // Otherwise, we could have used that as a way to failover to opening the // URI as a directory. Also, it would have been ideal if // gnome_vfs_get_file_info_from_handle were actually implemented by the // smb:// module, since that would have allowed us to potentially save a // round trip to the server to discover the mime type of the document in // the case where gnome_vfs_open would have been used. (Oh well! /me // throws hands up in the air and moves on...) GnomeVFSFileInfo info = {0}; rv = gnome_vfs_get_file_info(mSpec.get(), &info, GnomeVFSFileInfoOptions( GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS)); if (rv == GNOME_VFS_OK) { if (info.type == GNOME_VFS_FILE_TYPE_DIRECTORY) { rv = gnome_vfs_directory_list_load(&mDirList, mSpec.get(), GNOME_VFS_FILE_INFO_DEFAULT); LOG(("gnomevfs: gnome_vfs_directory_list_load returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } else { rv = gnome_vfs_open(&mHandle, mSpec.get(), GNOME_VFS_OPEN_READ); LOG(("gnomevfs: gnome_vfs_open returned %d (%s) [spec=\"%s\"]\n", rv, gnome_vfs_result_to_string(rv), mSpec.get())); } } gnome_vfs_module_callback_pop(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION); if (rv == GNOME_VFS_OK) { if (mHandle) { // Here we set the content type of the channel to the value of the mime // type determined by GnomeVFS. However, if GnomeVFS is telling us that // the document is binary, we'll ignore that and keep the channel's // content type unspecified. That will enable our content type sniffing // algorithms. This should provide more consistent mime type handling. if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0)) SetContentTypeOfChannel(info.mime_type); mBytesRemaining = info.size; // Update the content length attribute on the channel. We do this // synchronously without proxying. This hack is not as bad as it looks! if (mBytesRemaining != PRUint64(-1)) mChannel->SetContentLength(mBytesRemaining); } else { mDirOpen = PR_TRUE; // Sort mDirList mDirList = g_list_sort(mDirList, FileInfoComparator); mDirListPtr = mDirList; // Write base URL (make sure it ends with a '/') mDirBuf.Append("300: "); mDirBuf.Append(mSpec); if (mSpec.get()[mSpec.Length() - 1] != '/') mDirBuf.Append('/'); mDirBuf.Append('\n'); // Write column names mDirBuf.Append("200: filename content-length last-modified file-type\n"); // Write charset (assume UTF-8) // XXX is this correct? mDirBuf.Append("301: UTF-8\n"); SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT); } } gnome_vfs_file_info_clear(&info); return rv; }