1 //========================================================================
5 // All changes made under the Poppler project to this file are licensed
6 // under GPL version 2 or later
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 //========================================================================
30 EmbFile::EmbFile(Object
*efStream
)
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
46 if (dataDict
->lookup("Subtype", &subtypeName
)->isName()) {
47 m_mimetype
= new GooString(subtypeName
.getName());
51 // paramDict corresponds to Table 3.42 in the PDF1.6 spec
53 if (dataDict
->lookup("Params", ¶mDict
)->isDict()) {
55 if (paramDict
.dictLookup("ModDate", ¶mObj
)->isString())
56 m_modDate
= new GooString(paramObj
.getString());
59 if (paramDict
.dictLookup("CreationDate", ¶mObj
)->isString())
60 m_createDate
= new GooString(paramObj
.getString());
63 if (paramDict
.dictLookup("Size", ¶mObj
)->isInt())
64 m_size
= paramObj
.getInt();
67 if (paramDict
.dictLookup("CheckSum", ¶mObj
)->isString())
68 m_checksum
= new GooString(paramObj
.getString());
84 GBool
EmbFile::save(const char *path
) {
88 if (!(f
= fopen(path
, "wb"))) {
96 GBool
EmbFile::save2(FILE *f
) {
99 m_objStr
.streamReset();
100 while ((c
= m_objStr
.streamGetChar()) != EOF
) {
106 FileSpec::FileSpec(Object
*fileSpecA
)
110 platformFileName
= NULL
;
113 fileSpecA
->copy(&fileSpec
);
116 if (!getFileSpecName(fileSpecA
, &obj1
)) {
119 error(errSyntaxError
, -1, "Invalid FileSpec");
123 fileName
= obj1
.getString()->copy();
126 if (fileSpec
.isDict()) {
127 if (fileSpec
.dictLookup("EF", &obj1
)->isDict()) {
128 if (!obj1
.dictLookupNF("F", &fileStream
)->isRef()) {
131 error(errSyntaxError
, -1, "Invalid FileSpec: Embedded file stream is not an indirect reference");
139 if (fileSpec
.dictLookup("Desc", &obj1
)->isString())
140 desc
= obj1
.getString()->copy();
144 FileSpec::~FileSpec()
149 delete platformFileName
;
154 EmbFile
*FileSpec::getEmbeddedFile()
163 XRef
*xref
= fileSpec
.getDict()->getXRef();
164 embFile
= new EmbFile(fileStream
.fetch(xref
, &obj1
));
170 GooString
*FileSpec::getFileNameForPlatform()
172 if (platformFileName
)
173 return platformFileName
;
176 if (getFileSpecNameForPlatform(&fileSpec
, &obj1
))
177 platformFileName
= obj1
.getString()->copy();
180 return platformFileName
;
183 GBool
getFileSpecName (Object
*fileSpec
, Object
*fileName
)
185 if (fileSpec
->isString()) {
186 fileSpec
->copy(fileName
);
190 if (fileSpec
->isDict()) {
191 fileSpec
->dictLookup("UF", fileName
);
192 if (fileName
->isString()) {
196 fileSpec
->dictLookup("F", fileName
);
197 if (fileName
->isString()) {
201 fileSpec
->dictLookup("DOS", fileName
);
202 if (fileName
->isString()) {
206 fileSpec
->dictLookup("Mac", fileName
);
207 if (fileName
->isString()) {
211 fileSpec
->dictLookup("Unix", fileName
);
212 if (fileName
->isString()) {
220 GBool
getFileSpecNameForPlatform (Object
*fileSpec
, Object
*fileName
)
222 if (fileSpec
->isString()) {
223 fileSpec
->copy(fileName
);
227 if (fileSpec
->isDict()) {
228 if (!fileSpec
->dictLookup("UF", fileName
)->isString ()) {
230 if (!fileSpec
->dictLookup("F", fileName
)->isString ()) {
233 const char *platform
= "DOS";
235 const char *platform
= "Unix";
237 if (!fileSpec
->dictLookup(platform
, fileName
)->isString ()) {
239 error(errSyntaxError
, -1, "Illegal file spec");
245 error(errSyntaxError
, -1, "Illegal file spec");
249 // system-dependent path manipulation
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
258 if (name
->getChar(0) == '/') {
259 if (name
->getLength() >= 2 && name
->getChar(1) == '/') {
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, ':');
270 for (j
= 2; j
< name
->getLength(); ++j
) {
271 if (name
->getChar(j
-1) != '\\' &&
272 name
->getChar(j
) == '/') {
276 if (j
< name
->getLength()) {
277 name
->setChar(0, '\\');
278 name
->insert(0, '\\');
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) == '/') {