Subversion Repositories Scribus

Rev

Rev 5917 | Rev 7982 | 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
 
27
#include "fileunzip.h"
28
 
29
#include <stdlib.h>
30
#include <string.h>
31
#include <errno.h>
32
#include <fcntl.h>
2632 craig 33
 
34
#ifdef HAVE_SYS_TYPES_H
35
#include <sys/types.h>
36
#endif
37
#ifdef HAVE_SYS_STAT_H
1620 tsoots 38
#include <sys/stat.h>
2632 craig 39
#endif
1576 tsoots 40
 
2702 craig 41
#ifdef HAVE_UNISTD_H
1576 tsoots 42
# include <unistd.h>
2702 craig 43
#endif
44
 
2730 cbradney 45
#ifndef _MSC_VER
46
#include <utime.h>
47
#else
48
#include <direct.h>
49
#include <time.h>
50
#include <sys/utime.h>
51
#endif
1576 tsoots 52
 
53
#include <iostream>
54
#include "unzip.h"
55
#include <qdir.h>
56
 
5917 jghali 57
#include "scpaths.h"
58
 
1576 tsoots 59
#define CASESENSITIVITY (0)
60
#define WRITEBUFFERSIZE (8192)
61
#define MAXFILENAME (256)
62
 
63
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password);
64
int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password);
65
int mymkdir(const char* dirname);
66
int makedir (char *newdir);
67
void change_file_date(const char* filename, uLong dosdate, tm_unz tmu_date);
68
 
69
FileUnzip::FileUnzip(QString zipFilePath)
70
{
71
        zipFile = zipFilePath;
72
}
73
 
74
QString FileUnzip::getFile(QString name)
75
{
76
        QString pwd = QDir::currentDirPath();
5917 jghali 77
        QString outDir = ScPaths::getTempFileDir();
1576 tsoots 78
        QFile f(outDir);
79
        QFileInfo fi(f);
80
        if (!fi.isWritable())
5917 jghali 81
                outDir = ScPaths::getApplicationDataDir();
1576 tsoots 82
        QDir::setCurrent(outDir);
6382 craig 83
        const QCString zipfilename(zipFile.local8Bit());
84
        // NOTE that the ODF specification does not specify what text
85
        // encoding strings in a zip file must have. Given this, we're
86
        // forced to just guess. I've chosen to use the local 8 bit
87
        // encoding, but it's possible that latin-1 is more compatible
88
        // depending on the behaviour of the various ODF supporting
89
        // apps. --CR
90
        const QCString filename_to_extract(name.local8Bit());
91
        unzFile uf = unzOpen(zipfilename.data());;
92
        int ret = do_extract_onefile(uf,filename_to_extract.data(), 0, 1, NULL);
1576 tsoots 93
        unzCloseCurrentFile(uf);
94
        QDir::setCurrent(pwd);
95
        if (ret != 0)
96
                return NULL;
97
        else
98
                return outDir + name;
99
}
100
 
101
FileUnzip::~FileUnzip()
102
{
103
 
104
}
105
 
106
 
107
int mymkdir(char* dirname)
108
{
109
    int ret=0;
2730 cbradney 110
#ifndef _MSC_VER
1576 tsoots 111
    ret = mkdir (dirname,0775);
2730 cbradney 112
#else
113
        ret = _mkdir(dirname);
114
#endif
1576 tsoots 115
    return ret;
116
}
117
 
118
int makedir (char *newdir)
119
{
120
  char *buffer ;
121
  char *p;
122
  int  len = (int)strlen(newdir);
123
 
124
  if (len <= 0)
125
    return 0;
126
 
127
  buffer = (char*)malloc(len+1);
128
  strcpy(buffer,newdir);
129
 
130
  if (buffer[len-1] == '/') {
131
    buffer[len-1] = '\0';
132
  }
133
  if (mymkdir(buffer) == 0)
134
    {
135
      free(buffer);
136
      return 1;
137
    }
138
 
139
  p = buffer+1;
140
  while (1)
141
    {
142
      char hold;
143
 
144
      while(*p && *p != '\\' && *p != '/')
145
        p++;
146
      hold = *p;
147
      *p = 0;
148
      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
149
        {
150
          free(buffer);
151
          return 0;
152
        }
153
      if (hold == 0)
154
        break;
155
      *p++ = hold;
156
    }
157
  free(buffer);
158
  return 1;
159
}
160
 
161
 
162
 
163
int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password)
164
{
165
//    int err = UNZ_OK;
166
    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
167
        return 2;
168
 
169
    if (do_extract_currentfile(uf,&opt_extract_without_path,
170
                                      &opt_overwrite,
171
                                      password) == UNZ_OK)
172
        return 0;
173
    else
174
        return 1;
175
}
176
 
177
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int*, const char* password)
178
{
179
    char filename_inzip[256];
180
    char* filename_withoutpath;
181
    char* p;
182
    int err=UNZ_OK;
183
    FILE *fout=NULL;
184
    void* buf;
185
    uInt size_buf;
186
 
187
    unz_file_info file_info;
188
//    uLong ratio=0;
189
    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
190
 
191
    if (err!=UNZ_OK)
192
        return err;
193
 
194
    size_buf = WRITEBUFFERSIZE;
195
    buf = (void*)malloc(size_buf);
196
    if (buf==NULL)
197
        return UNZ_INTERNALERROR;
198
 
199
    p = filename_withoutpath = filename_inzip;
200
    while ((*p) != '\0')
201
    {
202
        if (((*p)=='/') || ((*p)=='\\'))
203
            filename_withoutpath = p+1;
204
        p++;
205
    }
206
 
207
    if ((*filename_withoutpath)=='\0')
208
    {
209
        if ((*popt_extract_without_path)==0)
210
            mymkdir(filename_inzip);
211
    }
212
    else
213
    {
214
        char* write_filename;
215
        int skip=0;
216
 
217
        if ((*popt_extract_without_path)==0)
218
            write_filename = filename_inzip;
219
        else
220
            write_filename = filename_withoutpath;
221
 
222
        err = unzOpenCurrentFilePassword(uf,password);
223
 
224
        if ((skip==0) && (err==UNZ_OK))
225
        {
226
            fout=fopen(write_filename,"wb");
227
 
228
            /* some zipfile don't contain directory alone before file */
229
            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
230
                                (filename_withoutpath!=(char*)filename_inzip))
231
            {
232
                char c=*(filename_withoutpath-1);
233
                *(filename_withoutpath-1)='\0';
234
                makedir(write_filename);
235
                *(filename_withoutpath-1)=c;
236
                fout=fopen(write_filename,"wb");
237
            }
238
        }
239
 
240
        if (fout!=NULL)
241
        {
242
 
243
            do
244
            {
245
                err = unzReadCurrentFile(uf,buf,size_buf);
246
                if (err<0)
247
                    break;
248
                if (err>0)
249
                    if (fwrite(buf,err,1,fout)!=1)
250
                    {
251
                        err=UNZ_ERRNO;
252
                        break;
253
                    }
254
            }
255
            while (err>0);
256
            if (fout)
257
                    fclose(fout);
258
 
259
            if (err==0)
260
                change_file_date(write_filename,file_info.dosDate,
261
                                 file_info.tmu_date);
262
        }
263
 
264
        if (err==UNZ_OK)
265
            err = unzCloseCurrentFile (uf);
266
        else
267
            unzCloseCurrentFile(uf); /* don't lose the error */
268
    }
269
 
270
    free(buf);
271
    return err;
272
}
273
 
274
/* change_file_date : change the date/time of a file
275
    filename : the filename of the file where date/time must be modified
276
    dosdate : the new date at the MSDos format (4 bytes)
277
    tmu_date : the SAME new date at the tm_unz format */
278
void change_file_date(const char* filename, uLong, tm_unz tmu_date)
279
{
280
  struct utimbuf ut;
281
  struct tm newdate;
282
  newdate.tm_sec = tmu_date.tm_sec;
283
  newdate.tm_min=tmu_date.tm_min;
284
  newdate.tm_hour=tmu_date.tm_hour;
285
  newdate.tm_mday=tmu_date.tm_mday;
286
  newdate.tm_mon=tmu_date.tm_mon;
287
  if (tmu_date.tm_year > 1900)
288
      newdate.tm_year=tmu_date.tm_year - 1900;
289
  else
290
      newdate.tm_year=tmu_date.tm_year ;
291
  newdate.tm_isdst=-1;
292
 
293
  ut.actime=ut.modtime=mktime(&newdate);
294
  utime(filename,&ut);
295
}
296
 
297