Subversion Repositories Scribus

Rev

Rev 6382 | Rev 7984 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
1576 tsoots 7
/***************************************************************************
8
 *   Copyright (C) 2004 by Riku Leino                                      *
9
 *   tsoots@gmail.com                                                      *
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU General Public License as published by  *
13
 *   the Free Software Foundation; either version 2 of the License, or     *
14
 *   (at your option) any later version.                                   *
15
 *                                                                         *
16
 *   This program is distributed in the hope that it will be useful,       *
17
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
18
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
19
 *   GNU General Public License for more details.                          *
20
 *                                                                         *
21
 *   You should have received a copy of the GNU General Public License     *
22
 *   along with this program; if not, write to the                         *
23
 *   Free Software Foundation, Inc.,                                       *
24
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
25
 ***************************************************************************/
26
 
7982 jghali 27
#include "scconfig.h"
1576 tsoots 28
#include "fileunzip.h"
29
 
30
#include <stdlib.h>
31
#include <string.h>
32
#include <errno.h>
33
#include <fcntl.h>
2632 craig 34
 
35
#ifdef HAVE_SYS_TYPES_H
36
#include <sys/types.h>
37
#endif
38
#ifdef HAVE_SYS_STAT_H
1620 tsoots 39
#include <sys/stat.h>
2632 craig 40
#endif
1576 tsoots 41
 
2702 craig 42
#ifdef HAVE_UNISTD_H
1576 tsoots 43
# include <unistd.h>
2702 craig 44
#endif
45
 
2730 cbradney 46
#ifndef _MSC_VER
47
#include <utime.h>
48
#else
49
#include <direct.h>
50
#include <time.h>
51
#include <sys/utime.h>
52
#endif
1576 tsoots 53
 
54
#include <iostream>
55
#include "unzip.h"
56
#include <qdir.h>
57
 
5917 jghali 58
#include "scpaths.h"
59
 
1576 tsoots 60
#define CASESENSITIVITY (0)
61
#define WRITEBUFFERSIZE (8192)
62
#define MAXFILENAME (256)
63
 
64
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password);
7982 jghali 65
int do_extract_onefile(unzFile uf, const QString& filename, int opt_extract_without_path, int opt_overwrite, const char* password);
66
FILE*    openfile(const QString& filename, const QString& mode);
67
unzFile  unzOpenFile(const QString& filename);
68
int mymkdir(const QString& dirname);
69
int makedir (const QString& newdir);
70
void change_file_date(const QString& filename, uLong dosdate, tm_unz tmu_date);
1576 tsoots 71
 
7982 jghali 72
#if defined(_WIN32) && defined(HAVE_UNICODE)
73
zlib_filefunc_def file_api;
74
static voidpf ZCALLBACK fopen_filefunc_unicode(voidpf opaque, const char *filename, int mode);
75
#define utimbuf _utimbuf
76
#endif
77
 
1576 tsoots 78
FileUnzip::FileUnzip(QString zipFilePath)
79
{
80
        zipFile = zipFilePath;
81
}
82
 
83
QString FileUnzip::getFile(QString name)
84
{
85
        QString pwd = QDir::currentDirPath();
5917 jghali 86
        QString outDir = ScPaths::getTempFileDir();
1576 tsoots 87
        QFile f(outDir);
88
        QFileInfo fi(f);
89
        if (!fi.isWritable())
5917 jghali 90
                outDir = ScPaths::getApplicationDataDir();
1576 tsoots 91
        QDir::setCurrent(outDir);
7982 jghali 92
        unzFile uf = unzOpenFile(zipFile);
93
        int ret = do_extract_onefile(uf,name, 0, 1, NULL);
1576 tsoots 94
        unzCloseCurrentFile(uf);
95
        QDir::setCurrent(pwd);
96
        if (ret != 0)
97
                return NULL;
98
        else
99
                return outDir + name;
100
}
101
 
102
FileUnzip::~FileUnzip()
103
{
104
 
105
}
106
 
7982 jghali 107
FILE* openfile(const QString& filename, const QString& mode)
108
{
109
        FILE* fout = NULL;
110
#if defined(_WIN32) && defined(HAVE_UNICODE)
111
        fout = _wfopen(filename.ucs2(), mode.ucs2());
112
#else
113
        QCString fname = filename.local8Bit();
114
        QCString fmode  = mode.local8Bit();
115
    fout = fopen(fname.data(), fmode.data());
116
#endif
117
        return fout;
118
}
1576 tsoots 119
 
7982 jghali 120
unzFile unzOpenFile(const QString& filename)
1576 tsoots 121
{
7982 jghali 122
        unzFile unz;
123
#if defined(_WIN32) && defined(HAVE_UNICODE)
124
        fill_fopen_filefunc(&file_api);
125
        file_api.zopen_file = fopen_filefunc_unicode;
126
        unz = unzOpen2((const char*)filename.ucs2(), &file_api);
127
#else
128
        QCString fname(filename.local8Bit());
129
        unz = unzOpen(fname.data());
130
#endif
131
        return unz;
132
}
133
 
134
#if defined(_WIN32) && defined(HAVE_UNICODE)
135
static voidpf ZCALLBACK fopen_filefunc_unicode(voidpf opaque, const char *filename, int mode)
136
{
137
        FILE* file = NULL;
138
        const wchar_t* mode_fopen = NULL;
139
        if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
140
                mode_fopen = L"rb";
141
        else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
142
                mode_fopen = L"r+b";
143
        else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
144
                mode_fopen = L"wb";
145
        if (!((filename == NULL) || (mode_fopen == NULL)))
146
                file = _wfopen((const wchar_t *)filename, mode_fopen);
147
        return file;
148
}
149
#endif
150
 
151
int mymkdir(const QString& dirname)
152
{
1576 tsoots 153
    int ret=0;
7982 jghali 154
#if defined(_WIN32) && defined(HAVE_UNICODE)
155
        ret = _wmkdir(dirname.ucs2());
156
#elif defined(_WIN32)
157
        QCString cdir = dirname.local8Bit();
158
    ret = _mkdir(cdir.data());
2730 cbradney 159
#else
7982 jghali 160
        QCString cdir = dirname.local8Bit();
161
    ret = mkdir (cdir.data(), 0775);
2730 cbradney 162
#endif
1576 tsoots 163
    return ret;
164
}
165
 
7982 jghali 166
int makedir (const QString& newdir)
1576 tsoots 167
{
7982 jghali 168
        QChar p;
169
        QString buffer;
170
        int len = newdir.length();
171
 
172
        if (len <= 0)
173
                return 0;
174
        buffer = newdir;
1576 tsoots 175
 
7982 jghali 176
        if (buffer.endsWith("/") || buffer.endsWith("\\"))
177
                buffer.left(len - 1);
1576 tsoots 178
 
7982 jghali 179
        if (mymkdir(buffer) == 0)
180
                return 1;
1576 tsoots 181
 
7982 jghali 182
        uint cIndex = 1;
183
        p = buffer[1];
184
        while (1)
185
        {
186
                QString tmpBuf;
187
                while(!p.isNull() && p != '\\' && p != '/')
188
                        p = buffer[cIndex++];
189
                tmpBuf = buffer.left(cIndex - 1);
190
                if ((mymkdir(tmpBuf) == -1) && (errno == ENOENT))
191
                        return 0;
192
                if (p.isNull())
193
                        break;
194
                p = buffer[++cIndex];
195
        }
196
        return 1;
1576 tsoots 197
}
198
 
7982 jghali 199
int do_extract_onefile(unzFile uf, const QString& filename, int opt_extract_without_path, int opt_overwrite, const char* password)
1576 tsoots 200
{
201
//    int err = UNZ_OK;
7982 jghali 202
        QCString fname = filename.local8Bit();
203
    if (unzLocateFile(uf,fname.data(),CASESENSITIVITY)!=UNZ_OK)
1576 tsoots 204
        return 2;
205
 
206
    if (do_extract_currentfile(uf,&opt_extract_without_path,
207
                                      &opt_overwrite,
208
                                      password) == UNZ_OK)
209
        return 0;
210
    else
211
        return 1;
212
}
213
 
214
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int*, const char* password)
215
{
7982 jghali 216
        char  fn_inzip[256];
217
        QString filename_inzip;
218
        QString filename_withoutpath;
219
        int err=UNZ_OK;
220
        FILE *fout=NULL;
221
        void* buf;
222
        uInt size_buf;
1576 tsoots 223
 
7982 jghali 224
        unz_file_info file_info;
225
        //uLong ratio=0;
226
        err = unzGetCurrentFileInfo(uf,&file_info,fn_inzip,sizeof(fn_inzip),NULL,0,NULL,0);
1576 tsoots 227
 
7982 jghali 228
        if (err!=UNZ_OK)
229
                return err;
1576 tsoots 230
 
7982 jghali 231
        size_buf = WRITEBUFFERSIZE;
232
        buf = (void*)malloc(size_buf);
233
        if (buf==NULL)
234
                return UNZ_INTERNALERROR;
1576 tsoots 235
 
7982 jghali 236
        QChar p;
237
        uint cIndex = 0;
238
        filename_inzip = QString::fromLocal8Bit(fn_inzip);
239
        filename_withoutpath = filename_inzip;
240
        for (uint i = 0; i < filename_inzip.length(); i++)
241
        {
242
                p = filename_inzip[i];
243
                if( (p == '/') || (p =='\\'))
244
                        filename_withoutpath = filename_inzip.mid(i+1);
245
        }
1576 tsoots 246
 
7982 jghali 247
        if (filename_withoutpath.isEmpty())
248
        {
249
                if ((*popt_extract_without_path)==0)
250
                        mymkdir(filename_inzip);
251
        }
252
        else
1576 tsoots 253
    {
7982 jghali 254
                QString write_filename;
255
                int skip=0;
1576 tsoots 256
 
7982 jghali 257
                if ((*popt_extract_without_path)==0)
258
                        write_filename = filename_inzip;
259
                else
260
                        write_filename = filename_withoutpath;
261
 
262
                err = unzOpenCurrentFilePassword(uf,password);
1576 tsoots 263
 
7982 jghali 264
                if ((skip==0) && (err==UNZ_OK))
265
                {
266
                        fout = openfile(write_filename, "wb");
1576 tsoots 267
            /* some zipfile don't contain directory alone before file */
7982 jghali 268
                        if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
269
                                                                (filename_withoutpath != filename_inzip))
270
                        {
271
                                uint len = filename_inzip.length() - filename_withoutpath.length() - 1;
272
                                QString write_dir = filename_inzip.left(len);
273
                                makedir(write_dir);
274
                                fout = openfile(write_filename, "wb");
275
                        }
276
                }
1576 tsoots 277
 
7982 jghali 278
                if (fout!=NULL)
279
                {
280
                        do
281
                        {
282
                                err = unzReadCurrentFile(uf,buf,size_buf);
283
                                if (err<0)
284
                                        break;
285
                                if (err>0)
286
                                        if (fwrite(buf,err,1,fout)!=1)
287
                                        {
288
                                                err=UNZ_ERRNO;
289
                                                break;
290
                                        }
291
                        }
292
                        while (err>0);
293
                        if (fout)
294
                                fclose(fout);
1576 tsoots 295
 
7982 jghali 296
                        if (err==0)
297
                                change_file_date(write_filename,file_info.dosDate,
298
                                                                        file_info.tmu_date);
299
                }
1576 tsoots 300
 
7982 jghali 301
                if (err==UNZ_OK)
302
                        err = unzCloseCurrentFile (uf);
303
                else
304
                        unzCloseCurrentFile(uf); /* don't lose the error */
305
        }
1576 tsoots 306
 
7982 jghali 307
        free(buf);
308
        return err;
1576 tsoots 309
}
310
 
311
/* change_file_date : change the date/time of a file
312
    filename : the filename of the file where date/time must be modified
313
    dosdate : the new date at the MSDos format (4 bytes)
314
    tmu_date : the SAME new date at the tm_unz format */
7982 jghali 315
void change_file_date(const QString& filename, uLong, tm_unz tmu_date)
1576 tsoots 316
{
7982 jghali 317
        struct utimbuf ut;
318
        struct tm newdate;
319
        newdate.tm_sec = tmu_date.tm_sec;
320
        newdate.tm_min=tmu_date.tm_min;
321
        newdate.tm_hour=tmu_date.tm_hour;
322
        newdate.tm_mday=tmu_date.tm_mday;
323
        newdate.tm_mon=tmu_date.tm_mon;
324
        if (tmu_date.tm_year > 1900)
325
                newdate.tm_year=tmu_date.tm_year - 1900;
326
        else
327
                newdate.tm_year=tmu_date.tm_year ;
328
        newdate.tm_isdst=-1;
1576 tsoots 329
 
7982 jghali 330
        ut.actime=ut.modtime=mktime(&newdate);
331
#if defined(_WIN32) && defined(HAVE_UNICODE)
332
        _wutime(filename.ucs2(), &ut);
333
#else
334
        QCString fname = filename.local8Bit();
335
        utime(fname.data(), &ut);
336
#endif
1576 tsoots 337
}