beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / FileSpec.cc
blobbac1eaea0d7e5c969a69283e90ef3ea8fca7e9cf
1 //========================================================================
2 //
3 // FileSpec.cc
4 //
5 // All changes made under the Poppler project to this file are licensed
6 // under GPL version 2 or later
7 //
8 // Copyright (C) 2008-2009 Carlos Garcia Campos <carlosgc@gnome.org>
9 // Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
10 // Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
11 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
13 // To see a description of the changes please see the Changelog file that
14 // came with your tarball or type make ChangeLog if you are building from git
16 //========================================================================
18 //========================================================================
20 // Most of the code from Link.cc and PSOutputDev.cc
22 // Copyright 1996-2003 Glyph & Cog, LLC
24 //========================================================================
26 #include <config.h>
28 #include "FileSpec.h"
30 EmbFile::EmbFile(Object *efStream)
32 m_size = -1;
33 m_createDate = NULL;
34 m_modDate = NULL;
35 m_checksum = NULL;
36 m_mimetype = NULL;
38 efStream->copy(&m_objStr);
40 if (efStream->isStream()) {
41 // dataDict corresponds to Table 3.41 in the PDF1.6 spec.
42 Dict *dataDict = efStream->streamGetDict();
44 // subtype is normally the mimetype
45 Object subtypeName;
46 if (dataDict->lookup("Subtype", &subtypeName)->isName()) {
47 m_mimetype = new GooString(subtypeName.getName());
49 subtypeName.free();
51 // paramDict corresponds to Table 3.42 in the PDF1.6 spec
52 Object paramDict;
53 if (dataDict->lookup("Params", &paramDict)->isDict()) {
54 Object paramObj;
55 if (paramDict.dictLookup("ModDate", &paramObj)->isString())
56 m_modDate = new GooString(paramObj.getString());
57 paramObj.free();
59 if (paramDict.dictLookup("CreationDate", &paramObj)->isString())
60 m_createDate = new GooString(paramObj.getString());
61 paramObj.free();
63 if (paramDict.dictLookup("Size", &paramObj)->isInt())
64 m_size = paramObj.getInt();
65 paramObj.free();
67 if (paramDict.dictLookup("CheckSum", &paramObj)->isString())
68 m_checksum = new GooString(paramObj.getString());
69 paramObj.free();
71 paramDict.free();
75 EmbFile::~EmbFile()
77 delete m_createDate;
78 delete m_modDate;
79 delete m_checksum;
80 delete m_mimetype;
81 m_objStr.free();
84 GBool EmbFile::save(const char *path) {
85 FILE *f;
86 GBool ret;
88 if (!(f = fopen(path, "wb"))) {
89 return gFalse;
91 ret = save2(f);
92 fclose(f);
93 return ret;
96 GBool EmbFile::save2(FILE *f) {
97 int c;
99 m_objStr.streamReset();
100 while ((c = m_objStr.streamGetChar()) != EOF) {
101 fputc(c, f);
103 return gTrue;
106 FileSpec::FileSpec(Object *fileSpecA)
108 ok = gTrue;
109 fileName = NULL;
110 platformFileName = NULL;
111 embFile = NULL;
112 desc = NULL;
113 fileSpecA->copy(&fileSpec);
115 Object obj1;
116 if (!getFileSpecName(fileSpecA, &obj1)) {
117 ok = gFalse;
118 obj1.free();
119 error(errSyntaxError, -1, "Invalid FileSpec");
120 return;
123 fileName = obj1.getString()->copy();
124 obj1.free();
126 if (fileSpec.isDict()) {
127 if (fileSpec.dictLookup("EF", &obj1)->isDict()) {
128 if (!obj1.dictLookupNF("F", &fileStream)->isRef()) {
129 ok = gFalse;
130 fileStream.free();
131 error(errSyntaxError, -1, "Invalid FileSpec: Embedded file stream is not an indirect reference");
132 obj1.free();
133 return;
136 obj1.free();
139 if (fileSpec.dictLookup("Desc", &obj1)->isString())
140 desc = obj1.getString()->copy();
141 obj1.free();
144 FileSpec::~FileSpec()
146 fileSpec.free();
147 fileStream.free();
148 delete fileName;
149 delete platformFileName;
150 delete embFile;
151 delete desc;
154 EmbFile *FileSpec::getEmbeddedFile()
156 if(!ok)
157 return NULL;
159 if (embFile)
160 return embFile;
162 Object obj1;
163 XRef *xref = fileSpec.getDict()->getXRef();
164 embFile = new EmbFile(fileStream.fetch(xref, &obj1));
165 obj1.free();
167 return embFile;
170 GooString *FileSpec::getFileNameForPlatform()
172 if (platformFileName)
173 return platformFileName;
175 Object obj1;
176 if (getFileSpecNameForPlatform(&fileSpec, &obj1))
177 platformFileName = obj1.getString()->copy();
178 obj1.free();
180 return platformFileName;
183 GBool getFileSpecName (Object *fileSpec, Object *fileName)
185 if (fileSpec->isString()) {
186 fileSpec->copy(fileName);
187 return gTrue;
190 if (fileSpec->isDict()) {
191 fileSpec->dictLookup("UF", fileName);
192 if (fileName->isString()) {
193 return gTrue;
195 fileName->free();
196 fileSpec->dictLookup("F", fileName);
197 if (fileName->isString()) {
198 return gTrue;
200 fileName->free();
201 fileSpec->dictLookup("DOS", fileName);
202 if (fileName->isString()) {
203 return gTrue;
205 fileName->free();
206 fileSpec->dictLookup("Mac", fileName);
207 if (fileName->isString()) {
208 return gTrue;
210 fileName->free();
211 fileSpec->dictLookup("Unix", fileName);
212 if (fileName->isString()) {
213 return gTrue;
215 fileName->free();
217 return gFalse;
220 GBool getFileSpecNameForPlatform (Object *fileSpec, Object *fileName)
222 if (fileSpec->isString()) {
223 fileSpec->copy(fileName);
224 return gTrue;
227 if (fileSpec->isDict()) {
228 if (!fileSpec->dictLookup("UF", fileName)->isString ()) {
229 fileName->free();
230 if (!fileSpec->dictLookup("F", fileName)->isString ()) {
231 fileName->free();
232 #ifdef _WIN32
233 const char *platform = "DOS";
234 #else
235 const char *platform = "Unix";
236 #endif
237 if (!fileSpec->dictLookup(platform, fileName)->isString ()) {
238 fileName->free();
239 error(errSyntaxError, -1, "Illegal file spec");
240 return gFalse;
244 } else {
245 error(errSyntaxError, -1, "Illegal file spec");
246 return gFalse;
249 // system-dependent path manipulation
250 #ifdef _WIN32
251 int i, j;
252 GooString *name = fileName->getString();
253 // "//...." --> "\...."
254 // "/x/...." --> "x:\...."
255 // "/server/share/...." --> "\\server\share\...."
256 // convert escaped slashes to slashes and unescaped slashes to backslashes
257 i = 0;
258 if (name->getChar(0) == '/') {
259 if (name->getLength() >= 2 && name->getChar(1) == '/') {
260 name->del(0);
261 i = 0;
262 } else if (name->getLength() >= 2 &&
263 ((name->getChar(1) >= 'a' && name->getChar(1) <= 'z') ||
264 (name->getChar(1) >= 'A' && name->getChar(1) <= 'Z')) &&
265 (name->getLength() == 2 || name->getChar(2) == '/')) {
266 name->setChar(0, name->getChar(1));
267 name->setChar(1, ':');
268 i = 2;
269 } else {
270 for (j = 2; j < name->getLength(); ++j) {
271 if (name->getChar(j-1) != '\\' &&
272 name->getChar(j) == '/') {
273 break;
276 if (j < name->getLength()) {
277 name->setChar(0, '\\');
278 name->insert(0, '\\');
279 i = 2;
283 for (; i < name->getLength(); ++i) {
284 if (name->getChar(i) == '/') {
285 name->setChar(i, '\\');
286 } else if (name->getChar(i) == '\\' &&
287 i+1 < name->getLength() &&
288 name->getChar(i+1) == '/') {
289 name->del(i);
292 #endif /* _WIN32 */
294 return gTrue;