[poppler] config.h.cmake configure.ac ConfigureChecks.cmake goo/gfile.cc goo/gfile.h poppler/GlobalParamsWin.cc poppler/PDFDoc.cc poppler/PDFDoc.h poppler/Stream.cc poppler/Stream.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Apr 4 15:00:39 PDT 2013


 ConfigureChecks.cmake      |    2 +
 config.h.cmake             |    6 +++
 configure.ac               |    1 
 goo/gfile.cc               |   80 +++++++++++++++++++++++++++++++++++++++++++++
 goo/gfile.h                |   30 ++++++++++++++++
 poppler/GlobalParamsWin.cc |   19 +++-------
 poppler/PDFDoc.cc          |   37 +++++---------------
 poppler/PDFDoc.h           |    4 +-
 poppler/Stream.cc          |   46 ++++++++-----------------
 poppler/Stream.h           |   17 ++-------
 10 files changed, 158 insertions(+), 84 deletions(-)

New commits:
commit 0a243c8c14d09a40f25338999c3ca06273277b45
Author: Adam Reichold <adamreichold at myopera.com>
Date:   Fri Apr 5 00:00:07 2013 +0200

    Add a GooFile class to encapsulate file read access using offsets
    
    Bug #62735

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 6e547ed..9f67b43 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -27,6 +27,8 @@ check_include_files(unistd.h HAVE_UNISTD_H)
 check_function_exists(fseek64 HAVE_FSEEK64)
 check_function_exists(fseeko HAVE_FSEEKO)
 check_function_exists(ftell64 HAVE_FTELL64)
+check_function_exists(pread64 HAVE_PREAD64)
+check_function_exists(lseek64 HAVE_LSEEK64)
 check_function_exists(gmtime_r HAVE_GMTIME_R)
 check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
 check_function_exists(localtime_r HAVE_LOCALTIME_R)
diff --git a/config.h.cmake b/config.h.cmake
index cde219f..c3b30db 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -46,6 +46,12 @@
 /* Define to 1 if you have the `ftell64' function. */
 #cmakedefine HAVE_FTELL64 1
 
+/* Define to 1 if you have the `pread64' function. */
+#cmakedefine HAVE_PREAD64 1
+
+/* Define to 1 if you have the `lseek64' function. */
+#cmakedefine HAVE_LSEEK64 1
+
 /* Defines if gettimeofday is available on your system */
 #cmakedefine HAVE_GETTIMEOFDAY 1
 
diff --git a/configure.ac b/configure.ac
index fc77b22..cd4645b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -264,6 +264,7 @@ AC_CHECK_FUNCS(ftell64, xpdf_cv_func_ftell64=yes, xpdf_cv_func_ftell64=no)
 if test "$xpdf_cv_func_fseek64" = yes -a "$xpdf_cv_func_ftell64" = yes; then
   AC_DEFINE(HAVE_FSEEK64)
 fi
+AC_CHECK_FUNCS(pread64 lseek64)
 
 dnl Test for zlib
 AC_ARG_ENABLE([zlib],
diff --git a/goo/gfile.cc b/goo/gfile.cc
index 7630e20..c46fd86 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -21,6 +21,7 @@
 // Copyright (C) 2008, 2010, 2012 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2009, 2012 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -585,6 +586,85 @@ Goffset GoffsetMax() {
 }
 
 //------------------------------------------------------------------------
+// GooFile
+//------------------------------------------------------------------------
+
+#ifdef _WIN32
+
+int GooFile::read(char *buf, int n, Goffset offset) const {
+  DWORD m;
+  
+  LARGE_INTEGER largeInteger = {0};
+  largeInteger.QuadPart = offset;
+  
+  OVERLAPPED overlapped = {0};
+  overlapped.Offset = largeInteger.LowPart;
+  overlapped.OffsetHigh = largeInteger.HighPart;
+
+  return FALSE == ReadFile(handle, buf, n, &m, &overlapped) ? -1 : m;
+}
+
+Goffset GooFile::size() const {
+  LARGE_INTEGER size = {-1,-1};
+  
+  GetFileSizeEx(handle, &size);
+
+  return size.QuadPart;
+}
+
+GooFile* GooFile::open(const GooString *fileName) {
+  HANDLE handle = CreateFile(fileName->getCString(),
+                              GENERIC_READ,
+                              FILE_SHARE_READ,
+                              NULL,
+                              OPEN_EXISTING,
+                              FILE_ATTRIBUTE_NORMAL, NULL);
+  
+  return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
+}
+
+GooFile* GooFile::open(const wchar_t *fileName) {
+  HANDLE handle = CreateFileW(fileName,
+                              GENERIC_READ,
+                              FILE_SHARE_READ,
+                              NULL,
+                              OPEN_EXISTING,
+                              FILE_ATTRIBUTE_NORMAL, NULL);
+  
+  return handle == INVALID_HANDLE_VALUE ? NULL : new GooFile(handle);
+}
+
+#else
+
+int GooFile::read(char *buf, int n, Goffset offset) const {
+#ifdef HAVE_PREAD64
+  return pread64(fd, buf, n, offset);
+#else
+  return pread(fd, buf, n, offset);
+#endif
+}
+
+Goffset GooFile::size() const {
+#ifdef HAVE_LSEEK64
+  return lseek64(fd, 0, SEEK_END);
+#else
+  return lseek(fd, 0, SEEK_END);
+#endif
+}
+
+GooFile* GooFile::open(const GooString *fileName) {
+#ifdef VMS
+  int fd = ::open(fileName->getCString(), Q_RDONLY, "ctx=stm");
+#else
+  int fd = ::open(fileName->getCString(), O_RDONLY);
+#endif
+  
+  return fd < 0 ? NULL : new GooFile(fd);
+}
+
+#endif // _WIN32
+
+//------------------------------------------------------------------------
 // GDir and GDirEntry
 //------------------------------------------------------------------------
 
diff --git a/goo/gfile.h b/goo/gfile.h
index 6787a6e..0caee71 100644
--- a/goo/gfile.h
+++ b/goo/gfile.h
@@ -18,6 +18,7 @@
 // Copyright (C) 2006 Kristian Høgsberg <krh at redhat.com>
 // Copyright (C) 2009, 2011, 2012 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -122,6 +123,35 @@ extern Goffset Gftell(FILE *f);
 extern Goffset GoffsetMax();
 
 //------------------------------------------------------------------------
+// GooFile
+//------------------------------------------------------------------------
+
+class GooFile
+{
+public:
+  int read(char *buf, int n, Goffset offset) const;
+  Goffset size() const;
+  
+  static GooFile *open(const GooString *fileName);
+  
+#ifdef _WIN32
+  static GooFile *open(const wchar_t *fileName);
+  
+  ~GooFile() { CloseHandle(handle); }
+  
+private:
+  GooFile(HANDLE handleA): handle(handleA) {}
+  HANDLE handle;
+#else
+  ~GooFile() { close(fd); }
+    
+private:
+  GooFile(int fdA) : fd(fdA) {}
+  int fd;
+#endif // _WIN32
+};
+
+//------------------------------------------------------------------------
 // GDir and GDirEntry
 //------------------------------------------------------------------------
 
diff --git a/poppler/GlobalParamsWin.cc b/poppler/GlobalParamsWin.cc
index e83c079..084b49b 100644
--- a/poppler/GlobalParamsWin.cc
+++ b/poppler/GlobalParamsWin.cc
@@ -6,6 +6,7 @@
    // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki at hiroshima-u.ac.jp>
    // Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
    // Copyright (C) 2012 Mark Brand <mabrand at mabrand.nl>
+   // Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 
 TODO: instead of a fixed mapping defined in displayFontTab, it could
 scan the whole fonts directory, parse TTF files and build font
@@ -408,9 +409,7 @@ void GlobalParams::setupBaseFonts(char * dir)
 {
     const char *dataRoot = popplerDataDir ? popplerDataDir : POPPLER_DATADIR;
     GooString *fileName = NULL;
-    struct stat buf;
-    FILE *file;
-    int size = 0;
+    GooFile *file;
 
     if (baseFontsInitialized)
         return;
@@ -453,15 +452,9 @@ void GlobalParams::setupBaseFonts(char * dir)
 
     fileName = new GooString(dataRoot);
     fileName->append("/cidfmap");
-    if (stat(fileName->getCString(), &buf) == 0) {
-      size = buf.st_size;
-    }
+
     // try to open file
-#ifdef VMS
-    file = fopen(fileName->getCString(), "rb", "ctx=stm");
-#else
-    file = fopen(fileName->getCString(), "rb");
-#endif
+    file = GooFile::open(fileName);
 
     if (file != NULL) {
       Parser *parser;
@@ -470,7 +463,7 @@ void GlobalParams::setupBaseFonts(char * dir)
       obj1.initNull();
       parser = new Parser(NULL,
 	      new Lexer(NULL,
-	      new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj1)),
+	      new FileStream(file, 0, gFalse, file->size(), &obj1)),
 	      gTrue);
       obj1.free();
       parser->getObj(&obj1);
@@ -498,7 +491,7 @@ void GlobalParams::setupBaseFonts(char * dir)
 	  parser->getObj(&obj1);
 	}
       }
-      fclose(file);
+      delete file;
       delete parser;
     }
 }
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 46ecea5..52d694f 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -29,6 +29,7 @@
 // Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -55,6 +56,7 @@
 #include <sys/stat.h>
 #include "goo/gstrtod.h"
 #include "goo/GooString.h"
+#include "goo/gfile.h"
 #include "poppler-config.h"
 #include "GlobalParams.h"
 #include "Page.h"
@@ -129,7 +131,6 @@ PDFDoc::PDFDoc()
 PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
 	       GooString *userPassword, void *guiDataA) {
   Object obj;
-  Goffset size = 0;
 #ifdef _WIN32
   int n, i;
 #endif
@@ -147,17 +148,8 @@ PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
   fileNameU[n] = L'\0';
 #endif
 
-  struct stat buf;
-  if (stat(fileName->getCString(), &buf) == 0) {
-     size = buf.st_size;
-  }
-
   // try to open file
-#ifdef VMS
-  file = fopen(fileName->getCString(), "rb", "ctx=stm");
-#else
-  file = fopen(fileName->getCString(), "rb");
-#endif
+  file = GooFile::open(fileName);
   if (file == NULL) {
     // fopen() has failed.
     // Keep a copy of the errno returned by fopen so that it can be 
@@ -170,7 +162,7 @@ PDFDoc::PDFDoc(GooString *fileNameA, GooString *ownerPassword,
 
   // create stream
   obj.initNull();
-  str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
+  str = new FileStream(file, 0, gFalse, file->size(), &obj);
 
   ok = setup(ownerPassword, userPassword);
 }
@@ -194,26 +186,17 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GooString *ownerPassword,
     fileNameU[i] = fileNameA[i];
   }
   fileNameU[fileNameLen] = L'\0';
-
-
+  
   // try to open file
   // NB: _wfopen is only available in NT
-  struct _stat buf;
-  int size = 0;
   version.dwOSVersionInfoSize = sizeof(version);
   GetVersionEx(&version);
   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-    if (_wstat(fileNameU, &buf) == 0) {
-      size = buf.st_size;
-    }
-    file = _wfopen(fileNameU, L"rb");
+    file = GooFile::open(fileNameU);
   } else {
-    if (_stat(fileName->getCString(), &buf) == 0) {
-      size = buf.st_size;
-    }
-    file = fopen(fileName->getCString(), "rb");
+    file = GooFile::open(fileName);
   }
-  if (!size || !file) {
+  if (!file) {
     error(errIO, -1, "Couldn't open file '{0:t}'", fileName);
     errCode = errOpenFile;
     return;
@@ -221,7 +204,7 @@ PDFDoc::PDFDoc(wchar_t *fileNameA, int fileNameLen, GooString *ownerPassword,
 
   // create stream
   obj.initNull();
-  str = new FileStream(file, fileName->getCString(), 0, gFalse, size, &obj);
+  str = new FileStream(file, 0, gFalse, file->size(), &obj);
 
   ok = setup(ownerPassword, userPassword);
 }
@@ -343,7 +326,7 @@ PDFDoc::~PDFDoc() {
     delete str;
   }
   if (file) {
-    fclose(file);
+    delete file;
   }
   if (fileName) {
     delete fileName;
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index cc9d2db..da9bf5b 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -25,6 +25,7 @@
 // Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -49,6 +50,7 @@
 #include "Stream.h"
 
 class GooString;
+class GooFile;
 class BaseStream;
 class OutputDev;
 class Links;
@@ -307,7 +309,7 @@ private:
 #ifdef _WIN32
   wchar_t *fileNameU;
 #endif
-  FILE *file;
+  GooFile *file;
   BaseStream *str;
   void *guiData;
   int pdfMajorVersion;
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 6ffd5d3..d5d26ec 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -28,6 +28,7 @@
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2012 Even Rouault <even.rouault at mines-paris.org>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -750,30 +751,14 @@ GBool StreamPredictor::getNextLine() {
 }
 
 //------------------------------------------------------------------------
-// UniqueFileStream
-//------------------------------------------------------------------------
-
-UniqueFileStream::UniqueFileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
-		       Goffset lengthA, Object *dictA):
-    FileStream(fA, fileNameA, startA, limitedA, lengthA, dictA) {
-  f = fopen(fileName, "rb");
-}
-
-UniqueFileStream::~UniqueFileStream() {
-  close();
-  fclose(f);
-}
-
-//------------------------------------------------------------------------
 // FileStream
 //------------------------------------------------------------------------
 
-FileStream::FileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
+FileStream::FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
 		       Goffset lengthA, Object *dictA):
     BaseStream(dictA, lengthA) {
-  f = fA;
-  fileName = fileNameA;
-  start = startA;
+  file = fileA;
+  offset = start = startA;
   limited = limitedA;
   length = lengthA;
   bufPtr = bufEnd = buf;
@@ -787,17 +772,17 @@ FileStream::~FileStream() {
 }
 
 BaseStream *FileStream::copy() {
-  return new UniqueFileStream(f, fileName, start, limited, length, &dict);
+  return new FileStream(file, start, limited, length, &dict);
 }
 
 Stream *FileStream::makeSubStream(Goffset startA, GBool limitedA,
 				  Goffset lengthA, Object *dictA) {
-  return new FileStream(f, fileName, startA, limitedA, lengthA, dictA);
+  return new FileStream(file, startA, limitedA, lengthA, dictA);
 }
 
 void FileStream::reset() {
-  savePos = Gftell(f);
-  Gfseek(f, start, SEEK_SET);
+  savePos = offset;
+  offset = start;
   saved = gTrue;
   bufPtr = bufEnd = buf;
   bufPos = start;
@@ -805,7 +790,7 @@ void FileStream::reset() {
 
 void FileStream::close() {
   if (saved) {
-    Gfseek(f, savePos, SEEK_SET);
+    offset = savePos;
     saved = gFalse;
   }
 }
@@ -823,7 +808,8 @@ GBool FileStream::fillBuf() {
   } else {
     n = fileStreamBufSize;
   }
-  n = fread(buf, 1, n, f);
+  n = file->read(buf, n, offset);
+  offset += n;
   bufEnd = buf + n;
   if (bufPtr >= bufEnd) {
     return gFalse;
@@ -835,15 +821,13 @@ void FileStream::setPos(Goffset pos, int dir) {
   Goffset size;
 
   if (dir >= 0) {
-    Gfseek(f, pos, SEEK_SET);
-    bufPos = pos;
+    offset = bufPos = pos;
   } else {
-    Gfseek(f, 0, SEEK_END);
-    size = Gftell(f);
+    size = file->size();
     if (pos > size)
       pos = size;
-    Gfseek(f, -pos, SEEK_END);
-    bufPos = Gftell(f);
+    offset = size - pos;
+    bufPos = offset;
   }
   bufPtr = bufEnd = buf;
 }
diff --git a/poppler/Stream.h b/poppler/Stream.h
index dfcd530..5347d66 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -24,6 +24,7 @@
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2013 Peter Breitenlohner <peb at mppmu.mpg.de>
+// Copyright (C) 2013 Adam Reichold <adamreichold at myopera.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -43,6 +44,7 @@
 #include "Object.h"
 #include "goo/GooMutex.h"
 
+class GooFile;
 class BaseStream;
 class CachedFile;
 
@@ -443,7 +445,7 @@ private:
 class FileStream: public BaseStream {
 public:
 
-  FileStream(FILE *fA, char *fileName, Goffset startA, GBool limitedA,
+  FileStream(GooFile* fileA, Goffset startA, GBool limitedA,
 	     Goffset lengthA, Object *dictA);
   virtual ~FileStream();
   virtual BaseStream *copy();
@@ -491,10 +493,9 @@ private:
       return n;
     }
 
-protected:
-  FILE *f;
-  char *fileName;
 private:
+  GooFile* file;
+  Goffset offset;
   Goffset start;
   GBool limited;
   char buf[fileStreamBufSize];
@@ -505,14 +506,6 @@ private:
   GBool saved;
 };
 
-class UniqueFileStream: public FileStream {
-public:
-
-  UniqueFileStream(FILE *fA, char *fileNameA, Goffset startA, GBool limitedA,
-	     Goffset lengthA, Object *dictA);
-  virtual ~UniqueFileStream();
-};
-
 //------------------------------------------------------------------------
 // CachedFileStream
 //------------------------------------------------------------------------


More information about the poppler mailing list