//FIXME: nuke this! char * Application::GetResourceAsPath (const Uri *resourceBase, const Uri *uri) { const char *filename; char *dirname, *path; char *canonicalized_filename; ManagedStreamCallbacks stream; unzFile zipfile; struct stat st; char buf[4096]; int nread; int fd; if (!get_resource_cb || !uri || uri->IsAbsolute ()) return NULL; // construct the path name for this resource filename = uri->ToString (); canonicalized_filename = Deployment::GetCurrent ()->CanonicalizeFileName (filename, false); path = g_build_filename (GetResourceRoot(), canonicalized_filename, NULL); g_free (canonicalized_filename); if (g_stat (path, &st) != -1) { // path exists, we're done return path; } // create the directory for our resource (keeping the relative path intact) dirname = g_path_get_dirname (path); if (g_mkdir_with_parents (dirname, 0700) == -1 && errno != EEXIST) { g_free (dirname); g_free (path); return NULL; } g_free (dirname); stream = get_resource_cb (resourceBase, uri); if (!stream.handle) { g_free (path); return NULL; } // reset the stream to 0 if (stream.CanSeek (stream.handle)) stream.Seek (stream.handle, 0, SEEK_SET); // create and save the buffer to disk if ((fd = g_open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) == -1) { stream.Close (stream.handle); g_free (path); return NULL; } // write the stream to disk do { if ((nread = stream.Read (stream.handle, buf, 0, sizeof (buf))) <= 0) break; if (write_all (fd, buf, (size_t) nread) == -1) { stream.Close (stream.handle); g_unlink (path); g_free (path); close (fd); return NULL; } } while (true); stream.Close (stream.handle); close (fd); // check to see if the resource is zipped if (!(zipfile = unzOpen (path))) { // nope, not zipped... return path; } // create a directory to contain our unzipped content if (!(dirname = CreateTempDir (path))) { unzClose (zipfile); g_free (dirname); g_unlink (path); g_free (path); return NULL; } // unzip the contents if (!ExtractAll (zipfile, dirname, CanonModeResource)) { RemoveDir (dirname); unzClose (zipfile); g_free (dirname); g_unlink (path); g_free (path); return NULL; } unzClose (zipfile); g_unlink (path); if (g_rename (dirname, path) == -1) { RemoveDir (dirname); g_free (dirname); g_free (path); return NULL; } g_free (dirname); return path; }
bool Application::GetResource (const Uri *resourceBase, const Uri *uri, NotifyFunc notify_cb, EventHandler write_cb, DownloaderAccessPolicy policy, HttpRequest::Options options, Cancellable *cancellable, gpointer user_data) { if (!uri) { g_warning ("Passing a null uri to Application::GetResource"); if (notify_cb) notify_cb (NotifyFailed, GPOINTER_TO_INT(NULL), user_data); return false; } if (get_resource_cb && !uri->IsAbsolute ()) { ManagedStreamCallbacks stream; if (!Uri::IsNullOrEmpty (uri)) { stream = get_resource_cb (resourceBase, uri); } else { memset (&stream, 0, sizeof (stream)); } if (stream.handle) { if (notify_cb) notify_cb (NotifyStarted, GPOINTER_TO_INT(NULL), user_data); if (write_cb) { char buf[4096]; int offset = 0; int nread; if (stream.CanSeek (stream.handle)) stream.Seek (stream.handle, 0, 0); HttpRequestWriteEventArgs *args = new HttpRequestWriteEventArgs (NULL, 0, 0); do { if ((nread = stream.Read (stream.handle, buf, 0, sizeof (buf))) <= 0) break; args->SetData (buf); args->SetOffset (offset); args->SetCount (nread); write_cb (this, args, user_data); offset += nread; } while (true); args->unref (); } if (notify_cb) notify_cb (NotifyCompleted, GPOINTER_TO_INT(NULL), user_data); stream.Close (stream.handle); return true; } } #if 0 // FIXME: drt 171 and 173 expect this to fail simply because the uri // begins with a '/', but other drts (like 238) depend on this // working. I give up. if (!uri->isAbsolute && uri->path && uri->path[0] == '/') { if (notify_cb) notify_cb (NotifyFailed, NULL, user_data); return false; } #endif //no get_resource_cb or empty stream HttpRequest *request; if (!(request = GetDeployment ()->CreateHttpRequest (options))) { if (notify_cb) notify_cb (NotifyFailed, GPOINTER_TO_INT(NULL), user_data); return false; } NotifyCtx *ctx = g_new (NotifyCtx, 1); ctx->user_data = user_data; ctx->notify_cb = notify_cb; ctx->write_cb = write_cb; ctx->request = request; if (notify_cb) { request->AddHandler (HttpRequest::ProgressChangedEvent, application_downloader_progress_changed, ctx); request->AddHandler (HttpRequest::StartedEvent, application_downloader_started, ctx); } if (cancellable) { cancellable->SetCancelFuncAndData (application_downloader_abort, request, ctx); } request->AddHandler (HttpRequest::WriteEvent, application_downloader_write, ctx); request->AddHandler (HttpRequest::StoppedEvent, application_downloader_stopped, ctx); request->Open ("GET", uri, resourceBase, policy); request->Send (); return true; }