1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * file-downloader.cpp: File Downloader class.
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
17 #include <glib/gstdio.h>
22 #include "file-downloader.h"
23 #include "zip/unzip.h"
27 //TODO: Move all the zip related semantics in here to clean up downloader.cpp
29 FileDownloader::FileDownloader (Downloader
*dl
) : InternalDownloader (dl
, Type::FILEDOWNLOADER
)
39 FileDownloader::~FileDownloader ()
51 FileDownloader::CleanupUnzipDir ()
63 FileDownloader::DownloadedFileIsZipped ()
70 if (!(zipfile
= unzOpen (filename
)))
79 FileDownloader::GetResponseText (const char *partname
, gint64
*size
)
89 if (!(path
= GetDownloadedFilename (partname
)))
92 if (g_stat (path
, &st
) == -1) {
98 stream
= new TextStream ();
100 if (!stream
->OpenFile (path
, true)) {
108 buf
= g_byte_array_new ();
109 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) > 0)
110 g_byte_array_append (buf
, (const guint8
*) buffer
, nread
);
114 g_byte_array_append (buf
, (const guint8
*) "", 1);
115 data
= (char *) buf
->data
;
117 g_byte_array_free (buf
, false);
120 data
= g_strdup ("");
128 FileDownloader::GetDownloadedFile ()
134 FileDownloader::GetDownloadedFilename (const char *partname
)
136 char *dirname
, *path
, *part
;
144 if (!partname
|| !partname
[0])
145 return g_strdup (filename
);
147 if (!DownloadedFileIsZipped ())
150 if (!unzipdir
&& !(unzipdir
= CreateTempDir (filename
)))
153 part
= g_ascii_strdown (partname
, -1);
154 path
= g_build_filename (unzipdir
, part
, NULL
);
155 if ((rv
= g_stat (path
, &st
)) == -1 && errno
== ENOENT
) {
156 if (strchr (part
, '/') != NULL
) {
157 // create the directory path
158 dirname
= g_path_get_dirname (path
);
159 rv
= g_mkdir_with_parents (dirname
, 0700);
162 if (rv
== -1 && errno
!= EEXIST
)
166 // open the zip archive...
167 if (!(zipfile
= unzOpen (filename
)))
170 // locate the file we want to extract... (2 = case-insensitive)
171 if (unzLocateFile (zipfile
, partname
, 2) != UNZ_OK
)
174 // open the requested part within the zip file
175 if (unzOpenCurrentFile (zipfile
) != UNZ_OK
)
178 // open the output file
179 if ((fd
= g_open (path
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0600)) == -1)
182 // extract the file from the zip archive... (closes the fd on success and fail)
183 if (!ExtractFile (zipfile
, fd
))
186 unzCloseCurrentFile (zipfile
);
188 } else if (rv
== -1) {
189 // irrecoverable error
199 unzCloseCurrentFile (zipfile
);
217 FileDownloader::GetUnzippedPath ()
219 char filename
[256], *p
;
230 if (!DownloadedFileIsZipped ())
231 return this->filename
;
233 if (!unzipdir
&& !(unzipdir
= CreateTempDir (this->filename
)))
239 // open the zip archive...
240 if (!(zip
= unzOpen (this->filename
)))
243 path
= g_string_new (unzipdir
);
244 g_string_append_c (path
, G_DIR_SEPARATOR
);
249 // extract all the parts
251 if (unzOpenCurrentFile (zip
) != UNZ_OK
)
254 unzGetCurrentFileInfo (zip
, &info
, filename
, sizeof (filename
),
257 // convert filename to lowercase
258 for (p
= filename
; *p
; p
++) {
259 if (*p
>= 'A' && *p
<= 'Z')
263 if ((name
= strrchr (filename
, '/'))) {
264 // make sure the full directory path exists, if not create it
265 g_string_append_len (path
, filename
, name
- filename
);
266 g_mkdir_with_parents (path
->str
, 0700);
267 g_string_append (path
, name
);
269 g_string_append (path
, filename
);
272 if ((fd
= g_open (path
->str
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) != -1) {
273 if (!ExtractFile (zip
, fd
))
275 } else if (errno
!= EEXIST
) {
279 g_string_truncate (path
, len
);
280 unzCloseCurrentFile (zip
);
281 } while (unzGoToNextFile (zip
) == UNZ_OK
);
283 g_string_free (path
, true);
290 FileDownloader::Open (const char *verb
, const char *uri
)
305 dl
->InternalOpen (verb
, uri
);
309 FileDownloader::Write (void *buf
, gint32 offset
, gint32 n
)
311 dl
->InternalWrite (buf
, offset
, n
);