Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
411 Franz 1
/***************************************************************************
2
 *   Copyright (C) 2004 by Riku Leino                                      *
3
 *   tsoots@welho.com                                                      *
4
 *                                                                         *
5
 *   This program is free software; you can redistribute it and/or modify  *
6
 *   it under the terms of the GNU General Public License as published by  *
7
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 *   (at your option) any later version.                                   *
9
 *                                                                         *
10
 *   This program is distributed in the hope that it will be useful,       *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 *   GNU General Public License for more details.                          *
14
 *                                                                         *
15
 *   You should have received a copy of the GNU General Public License     *
16
 *   along with this program; if not, write to the                         *
17
 *   Free Software Foundation, Inc.,                                       *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 ***************************************************************************/
20
 
21
#include "sxwunzip.h"
22
 
23
#ifdef HAVE_XML
24
 
25
#include <stdlib.h>
26
#include <string.h>
27
#include <errno.h>
28
#include <fcntl.h>
29
 
30
#ifdef unix
31
# include <unistd.h>
32
# include <utime.h>
33
#else
34
# include <direct.h>
35
# include <io.h>
36
#endif
37
 
38
#include <iostream>
39
#include "unzip.h"
40
#include <qdir.h>
41
 
42
#define CASESENSITIVITY (0)
43
#define WRITEBUFFERSIZE (8192)
44
#define MAXFILENAME (256)
45
 
46
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password);
47
int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password);
48
int mymkdir(const char* dirname);
49
int makedir (char *newdir);
50
void change_file_date(const char* filename, uLong dosdate, tm_unz tmu_date);
51
 
52
SxwUnzip::SxwUnzip(QString zipFilePath)
53
{
54
        zipFile = zipFilePath;
55
}
56
 
57
QString SxwUnzip::getFile(QString name)
58
{
59
        QString pwd = QDir::currentDirPath();
60
        QString outDir = zipFile.left(zipFile.findRev("/") + 1);
61
        QFile f(outDir);
62
        QFileInfo fi(f);
63
        if (!fi.isWritable())
64
                outDir = QDir::homeDirPath() + "/.scribus/";
65
        QDir::setCurrent(outDir);
66
        const char *zipfilename = zipFile.ascii();
67
        const char *filename_to_extract = name.ascii();
68
        unzFile uf = unzOpen(zipfilename);;
69
        int ret = do_extract_onefile(uf,filename_to_extract, 0, 1, NULL);
70
        unzCloseCurrentFile(uf);
71
        QDir::setCurrent(pwd);
72
        if (ret != 0)
73
                return NULL;
74
        else
75
                return outDir + name;
76
}
77
 
78
SxwUnzip::~SxwUnzip()
79
{
80
 
81
}
82
 
83
 
84
int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password)
85
{
415 Franz 86
//    int err = UNZ_OK;
411 Franz 87
    if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
88
        return 2;
89
 
90
    if (do_extract_currentfile(uf,&opt_extract_without_path,
91
                                      &opt_overwrite,
92
                                      password) == UNZ_OK)
93
        return 0;
94
    else
95
        return 1;
96
}
97
 
98
int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, int* popt_overwrite, const char* password)
99
{
100
    char filename_inzip[256];
101
    char* filename_withoutpath;
102
    char* p;
103
    int err=UNZ_OK;
104
    FILE *fout=NULL;
105
    void* buf;
106
    uInt size_buf;
107
 
108
    unz_file_info file_info;
109
//    uLong ratio=0;
110
    err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
111
 
112
    if (err!=UNZ_OK)
113
        return err;
114
 
115
    size_buf = WRITEBUFFERSIZE;
116
    buf = (void*)malloc(size_buf);
117
    if (buf==NULL)
118
        return UNZ_INTERNALERROR;
119
 
120
    p = filename_withoutpath = filename_inzip;
121
    while ((*p) != '\0')
122
    {
123
        if (((*p)=='/') || ((*p)=='\\'))
124
            filename_withoutpath = p+1;
125
        p++;
126
    }
127
 
128
    if ((*filename_withoutpath)=='\0')
129
    {
130
        if ((*popt_extract_without_path)==0)
131
            mymkdir(filename_inzip);
132
    }
133
    else
134
    {
135
        char* write_filename;
136
        int skip=0;
137
 
138
        if ((*popt_extract_without_path)==0)
139
            write_filename = filename_inzip;
140
        else
141
            write_filename = filename_withoutpath;
142
 
143
        err = unzOpenCurrentFilePassword(uf,password);
144
 
145
        if ((skip==0) && (err==UNZ_OK))
146
        {
147
            fout=fopen(write_filename,"wb");
148
 
149
            /* some zipfile don't contain directory alone before file */
150
            if ((fout==NULL) && ((*popt_extract_without_path)==0) &&
151
                                (filename_withoutpath!=(char*)filename_inzip))
152
            {
153
                char c=*(filename_withoutpath-1);
154
                *(filename_withoutpath-1)='\0';
155
                makedir(write_filename);
156
                *(filename_withoutpath-1)=c;
157
                fout=fopen(write_filename,"wb");
158
            }
159
        }
160
 
161
        if (fout!=NULL)
162
        {
163
 
164
            do
165
            {
166
                err = unzReadCurrentFile(uf,buf,size_buf);
167
                if (err<0)
168
                    break;
169
                if (err>0)
170
                    if (fwrite(buf,err,1,fout)!=1)
171
                    {
172
                        err=UNZ_ERRNO;
173
                        break;
174
                    }
175
            }
176
            while (err>0);
177
            if (fout)
178
                    fclose(fout);
179
 
180
            if (err==0)
181
                change_file_date(write_filename,file_info.dosDate,
182
                                 file_info.tmu_date);
183
        }
184
 
185
        if (err==UNZ_OK)
186
            err = unzCloseCurrentFile (uf);
187
        else
188
            unzCloseCurrentFile(uf); /* don't lose the error */
189
    }
190
 
191
    free(buf);
192
    return err;
193
}
194
 
195
int mymkdir(char* dirname)
196
{
197
    int ret=0;
198
#ifdef WIN32
199
    ret = mkdir(dirname);
200
#else
201
#ifdef unix
202
    ret = mkdir (dirname,0775);
203
#endif
204
#endif
205
    return ret;
206
}
207
 
208
int makedir (const char *newdir)
209
{
210
  char *buffer ;
211
  char *p;
212
  int  len = (int)strlen(newdir);
213
 
214
  if (len <= 0)
215
    return 0;
216
 
217
  buffer = (char*)malloc(len+1);
218
  strcpy(buffer,newdir);
219
 
220
  if (buffer[len-1] == '/') {
221
    buffer[len-1] = '\0';
222
  }
223
  if (mymkdir(buffer) == 0)
224
    {
225
      free(buffer);
226
      return 1;
227
    }
228
 
229
  p = buffer+1;
230
  while (1)
231
    {
232
      char hold;
233
 
234
      while(*p && *p != '\\' && *p != '/')
235
        p++;
236
      hold = *p;
237
      *p = 0;
238
      if ((mymkdir(buffer) == -1) && (errno == ENOENT))
239
        {
240
          free(buffer);
241
          return 0;
242
        }
243
      if (hold == 0)
244
        break;
245
      *p++ = hold;
246
    }
247
  free(buffer);
248
  return 1;
249
}
250
 
251
/* change_file_date : change the date/time of a file
252
    filename : the filename of the file where date/time must be modified
253
    dosdate : the new date at the MSDos format (4 bytes)
254
    tmu_date : the SAME new date at the tm_unz format */
255
void change_file_date(const char* filename, uLong dosdate, tm_unz tmu_date)
256
{
257
#ifdef WIN32
258
  HANDLE hFile;
259
  FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite;
260
 
261
  hFile = CreateFile(filename,GENERIC_READ | GENERIC_WRITE,
262
                      0,NULL,OPEN_EXISTING,0,NULL);
263
  GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
264
  DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
265
  LocalFileTimeToFileTime(&ftLocal,&ftm);
266
  SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
267
  CloseHandle(hFile);
268
#else
269
#ifdef unix
270
  struct utimbuf ut;
271
  struct tm newdate;
272
  newdate.tm_sec = tmu_date.tm_sec;
273
  newdate.tm_min=tmu_date.tm_min;
274
  newdate.tm_hour=tmu_date.tm_hour;
275
  newdate.tm_mday=tmu_date.tm_mday;
276
  newdate.tm_mon=tmu_date.tm_mon;
277
  if (tmu_date.tm_year > 1900)
278
      newdate.tm_year=tmu_date.tm_year - 1900;
279
  else
280
      newdate.tm_year=tmu_date.tm_year ;
281
  newdate.tm_isdst=-1;
282
 
283
  ut.actime=ut.modtime=mktime(&newdate);
284
  utime(filename,&ut);
285
#endif
286
#endif
287
}
288
 
289
#endif // HAVE_XML
290