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>
21 #include "file-downloader.h"
22 #include "zip/unzip.h"
26 //TODO: Move all the zip related semantics in here to clean up downloader.cpp
28 FileDownloader::FileDownloader (Downloader
*dl
) : InternalDownloader (dl
, Type::FILEDOWNLOADER
)
38 FileDownloader::~FileDownloader ()
50 FileDownloader::CleanupUnzipDir ()
62 FileDownloader::DownloadedFileIsZipped ()
69 if (!(zipfile
= unzOpen (filename
)))
78 FileDownloader::GetResponseText (const char *partname
, gint64
*size
)
88 if (!(path
= GetDownloadedFilename (partname
)))
91 if (g_stat (path
, &st
) == -1) {
97 stream
= new TextStream ();
99 if (!stream
->OpenFile (path
, true)) {
107 buf
= g_byte_array_new ();
108 while ((nread
= stream
->Read (buffer
, sizeof (buffer
))) > 0)
109 g_byte_array_append (buf
, (const guint8
*) buffer
, nread
);
113 g_byte_array_append (buf
, (const guint8
*) "", 1);
114 data
= (char *) buf
->data
;
116 g_byte_array_free (buf
, false);
119 data
= g_strdup ("");
127 FileDownloader::GetDownloadedFile ()
133 FileDownloader::GetDownloadedFilename (const char *partname
)
135 char *dirname
, *path
, *part
;
143 if (!partname
|| !partname
[0])
144 return g_strdup (filename
);
146 if (!DownloadedFileIsZipped ())
149 if (!unzipdir
&& !(unzipdir
= CreateTempDir (filename
)))
152 part
= g_ascii_strdown (partname
, -1);
153 path
= g_build_filename (unzipdir
, part
, NULL
);
154 if ((rv
= g_stat (path
, &st
)) == -1 && errno
== ENOENT
) {
155 if (strchr (part
, '/') != NULL
) {
156 // create the directory path
157 dirname
= g_path_get_dirname (path
);
158 rv
= g_mkdir_with_parents (dirname
, 0700);
161 if (rv
== -1 && errno
!= EEXIST
)
165 // open the zip archive...
166 if (!(zipfile
= unzOpen (filename
)))
169 // locate the file we want to extract... (2 = case-insensitive)
170 if (unzLocateFile (zipfile
, partname
, 2) != UNZ_OK
)
173 // open the requested part within the zip file
174 if (unzOpenCurrentFile (zipfile
) != UNZ_OK
)
177 // open the output file
178 if ((fd
= g_open (path
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0600)) == -1)
181 // extract the file from the zip archive... (closes the fd on success and fail)
182 if (!ExtractFile (zipfile
, fd
))
185 unzCloseCurrentFile (zipfile
);
187 } else if (rv
== -1) {
188 // irrecoverable error
198 unzCloseCurrentFile (zipfile
);
216 FileDownloader::GetUnzippedPath ()
218 char filename
[256], *p
;
229 if (!DownloadedFileIsZipped ())
230 return this->filename
;
232 if (!unzipdir
&& !(unzipdir
= CreateTempDir (this->filename
)))
238 // open the zip archive...
239 if (!(zip
= unzOpen (this->filename
)))
242 path
= g_string_new (unzipdir
);
243 g_string_append_c (path
, G_DIR_SEPARATOR
);
248 // extract all the parts
250 if (unzOpenCurrentFile (zip
) != UNZ_OK
)
253 unzGetCurrentFileInfo (zip
, &info
, filename
, sizeof (filename
),
256 // convert filename to lowercase
257 for (p
= filename
; *p
; p
++) {
258 if (*p
>= 'A' && *p
<= 'Z')
262 if ((name
= strrchr (filename
, '/'))) {
263 // make sure the full directory path exists, if not create it
264 g_string_append_len (path
, filename
, name
- filename
);
265 g_mkdir_with_parents (path
->str
, 0700);
266 g_string_append (path
, name
);
268 g_string_append (path
, filename
);
271 if ((fd
= g_open (path
->str
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600)) != -1) {
272 if (!ExtractFile (zip
, fd
))
274 } else if (errno
!= EEXIST
) {
278 g_string_truncate (path
, len
);
279 unzCloseCurrentFile (zip
);
280 } while (unzGoToNextFile (zip
) == UNZ_OK
);
282 g_string_free (path
, true);
289 FileDownloader::Open (const char *verb
, const char *uri
)
304 dl
->InternalOpen (verb
, uri
);
308 FileDownloader::Write (void *buf
, gint32 offset
, gint32 n
)
310 dl
->InternalWrite (buf
, offset
, n
);