1 /***************************************************************************
2 * Copyright (C) 2006 by Dominik Seichter *
3 * domseichter@web.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU Library General Public License as *
7 * published by the Free Software Foundation; either version 2 of the *
8 * License, or (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 Library General Public *
16 * License 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 * In addition, as a special exception, the copyright holders give *
21 * permission to link the code of portions of this program with the *
22 * OpenSSL library under certain conditions as described in each *
23 * individual source file, and distribute linked combinations *
24 * including the two. *
25 * You must obey the GNU General Public License in all respects *
26 * for all of the code used other than OpenSSL. If you modify *
27 * file(s) with this exception, you may extend this exception to your *
28 * version of the file(s), but you are not obligated to do so. If you *
29 * do not wish to do so, delete this exception statement from your *
30 * version. If you delete this exception statement from all source *
31 * files in the program, then also delete it here. *
32 ***************************************************************************/
33
34 #ifndef _PDF_ERROR_H_
35 #define _PDF_ERROR_H_
36
37 // PdfError.h should not include PdfDefines.h, since it is included by it.
38 // It should avoid depending on anything defined in PdfDefines.h .
39
40 #include "podofoapi.h"
41 #include <string>
42 #include <queue>
43 #include <cstdarg>
44
45 #if defined(_MSC_VER) && _MSC_VER <= 1200 // same pragma as in PdfDefines.h which we cannot include here
46 #pragma warning(disable: 4251)
47 #pragma warning(disable: 4275)
48 #endif
49
50 /** \file PdfError.h
51 * Error information and logging is implemented in this file.
52 */
53
54 namespace PoDoFo {
55
56 /** Error Code enum values which are used in PdfError to describe the error.
57 *
58 * If you add an error code to this enum, please also add it
59 * to PdfError::ErrorName() and PdfError::ErrorMessage().
60 *
61 * \see PdfError
62 */
63 enum EPdfError {
64 ePdfError_ErrOk = 0, /**< The default value indicating no error. */
65
66 ePdfError_TestFailed, /**< Used in PoDoFo tests, to indicate that a test failed for some reason. */
67
68 ePdfError_InvalidHandle, /**< Null pointer was passed, but null pointer is not allowed. */
69 ePdfError_FileNotFound, /**< A file was not found or cannot be opened. */
70 ePdfError_InvalidDeviceOperation, /**< Tried to do something unsupported to an I/O device like seek a non-seekable input device */
71 ePdfError_UnexpectedEOF, /**< End of file was reached but data was expected. */
72 ePdfError_OutOfMemory, /**< Not enough memory to complete an operation. */
73 ePdfError_ValueOutOfRange, /**< The specified memory is out of the allowed range. */
74 ePdfError_InternalLogic, /**< An internal sanity check or assertion failed. */
75 ePdfError_InvalidEnumValue, /**< An invalid enum value was specified. */
76 ePdfError_BrokenFile, /**< The file content is broken. */
77
78 ePdfError_PageNotFound, /**< The requested page could not be found in the PDF. */
79
80 ePdfError_NoPdfFile, /**< The file is no PDF file. */
81 ePdfError_NoXRef, /**< The PDF file has no or an invalid XRef table. */
82 ePdfError_NoTrailer, /**< The PDF file has no or an invalid trailer. */
83 ePdfError_NoNumber, /**< A number was expected in the PDF file, but the read string is no number. */
84 ePdfError_NoObject, /**< A object was expected and none was found. */
85 ePdfError_NoEOFToken, /**< The PDF file has no or an invalid EOF marker. */
86
87 ePdfError_InvalidTrailerSize, /**< The trailer size is invalid. */
88 ePdfError_InvalidLinearization, /**< The linearization directory of a web-optimized PDF file is invalid. */
89 ePdfError_InvalidDataType, /**< The passed datatype is invalid or was not recognized */
90 ePdfError_InvalidXRef, /**< The XRef table is invalid */
91 ePdfError_InvalidXRefStream, /**< A XRef steam is invalid */
92 ePdfError_InvalidXRefType, /**< The XRef type is invalid or was not found */
93 ePdfError_InvalidPredictor, /**< Invalid or unimplemented predictor */
94 ePdfError_InvalidStrokeStyle, /**< Invalid stroke style during drawing */
95 ePdfError_InvalidHexString, /**< Invalid hex string */
96 ePdfError_InvalidStream, /**< The stream is invalid */
97 ePdfError_InvalidStreamLength, /**< The stream length is invalid */
98 ePdfError_InvalidKey, /**< The specified key is invalid */
99 ePdfError_InvalidName, /**< The specified Name is not valid in this context */
100 ePdfError_InvalidEncryptionDict, /**< The encryption dictionary is invalid or misses a required key */
101 ePdfError_InvalidPassword, /**< The password used to open the PDF file was invalid */
102 ePdfError_InvalidFontFile, /**< The font file is invalid */
103 ePdfError_InvalidContentStream, /**< The content stream is invalid due to mismatched context pairing or other problems */
104
105 ePdfError_UnsupportedFilter, /**< The requested filter is not yet implemented. */
106 ePdfError_UnsupportedFontFormat, /**< This font format is not supported by PoDoFo. */
107 ePdfError_ActionAlreadyPresent, /**< An Action was already present when trying to add a Destination */
108 ePdfError_WrongDestinationType, /**< The requested field is not available for the given destination type */
109
110 ePdfError_MissingEndStream, /**< The required token endstream was not found. */
111 ePdfError_Date, /**< Date/time error */
112 ePdfError_Flate, /**< Error in zlib */
113 ePdfError_FreeType, /**< Error in FreeType */
114 ePdfError_SignatureError, /**< Error in signature */
115
116 ePdfError_MutexError, /**< Error during a mutex operation */
117
118 ePdfError_UnsupportedImageFormat, /**< This image format is not supported by PoDoFo. */
119 ePdfError_CannotConvertColor, /**< This color format cannot be converted. */
120
121 ePdfError_NotImplemented, /**< This feature is currently not implemented. */
122
123 ePdfError_DestinationAlreadyPresent,/**< A destination was already present when trying to add an Action */
124 ePdfError_ChangeOnImmutable, /**< Changing values on immutable objects is not allowed. */
125
126 ePdfError_NotCompiled, /**< This feature was disabled at compile time. */
127
128 ePdfError_OutlineItemAlreadyPresent,/**< An outline item to be inserted was already in that outlines tree. */
129 ePdfError_NotLoadedForUpdate, /**< The document had not been loaded for update. */
130 ePdfError_CannotEncryptedForUpdate, /**< Cannot load encrypted documents for update. */
131
132 ePdfError_Unknown = 0xffff /**< Unknown error */
133 };
134
135 /**
136 * Used in PdfError::LogMessage to specify the log level.
137 *
138 * \see PdfError::LogMessage
139 */
140 enum ELogSeverity {
141 eLogSeverity_Critical, /**< Critical unexpected error */
142 eLogSeverity_Error, /**< Error */
143 eLogSeverity_Warning, /**< Warning */
144 eLogSeverity_Information, /**< Information message */
145 eLogSeverity_Debug, /**< Debug information */
146 eLogSeverity_None, /**< No specified level */
147
148 eLogSeverity_Unknown = 0xffff /**< Unknown log level */
149 };
150
151 /** \def PODOFO_RAISE_ERROR( x )
152 *
153 * Throw an exception of type PdfError with the error code x, which should be
154 * one of the values of the enum EPdfError. File and line info are included.
155 */
156 #define PODOFO_RAISE_ERROR( x ) throw ::PoDoFo::PdfError( x, __FILE__, __LINE__ );
157
158 /** \def PODOFO_RAISE_ERROR_INFO( x, y )
159 *
160 * Throw an exception of type PdfError with the error code x, which should be
161 * one of the values of the enum EPdfError. File and line info are included.
162 * Additionally extra information on the error, y is set, which will also be
163 * output by PdfError::PrintErrorMsg().
164 * y can be a C string, but can also be a C++ std::string.
165 */
166 #define PODOFO_RAISE_ERROR_INFO( x, y ) throw ::PoDoFo::PdfError( x, __FILE__, __LINE__, y );
167
168 /** \def PODOFO_RAISE_LOGIC_IF( x, y )
169 *
170 * Evaluate `x' as a binary predicate and if it is true, raise a logic error with the
171 * info string `y' .
172 */
173 #define PODOFO_RAISE_LOGIC_IF( x, y ) { if (x) throw ::PoDoFo::PdfError( ePdfError_InternalLogic, __FILE__, __LINE__, y ); };
174
175 class PODOFO_API PdfErrorInfo {
176 public:
177 PdfErrorInfo();
178 PdfErrorInfo( int line, const char* pszFile, const char* pszInfo );
179 PdfErrorInfo( int line, const char* pszFile, std::string pszInfo );
180 PdfErrorInfo( int line, const char* pszFile, const wchar_t* pszInfo );
181 PdfErrorInfo( const PdfErrorInfo & rhs );
182
183 const PdfErrorInfo & operator=( const PdfErrorInfo & rhs );
184
GetLine()185 inline int GetLine() const { return m_nLine; }
GetFilename()186 inline const std::string & GetFilename() const { return m_sFile; }
GetInformation()187 inline const std::string & GetInformation() const { return m_sInfo; }
GetInformationW()188 inline const std::wstring & GetInformationW() const { return m_swInfo; }
189
SetInformation(const char * pszInfo)190 inline void SetInformation( const char* pszInfo ) { m_sInfo = pszInfo ? pszInfo : ""; }
SetInformation(std::string pszInfo)191 inline void SetInformation( std::string pszInfo ) { m_sInfo = pszInfo; }
SetInformation(const wchar_t * pszInfo)192 inline void SetInformation( const wchar_t* pszInfo ) { m_swInfo = pszInfo ? pszInfo : L""; }
193
194 private:
195 int m_nLine;
196 std::string m_sFile;
197 std::string m_sInfo;
198 std::wstring m_swInfo;
199 };
200
201
202 typedef std::deque<PdfErrorInfo> TDequeErrorInfo;
203 typedef TDequeErrorInfo::iterator TIDequeErrorInfo;
204 typedef TDequeErrorInfo::const_iterator TCIDequeErrorInfo;
205
206
207 // This is required to generate the documentation with Doxygen.
208 // Without this define doxygen thinks we have a class called PODOFO_EXCEPTION_API(PODOFO_API) ...
209 #define PODOFO_EXCEPTION_API_DOXYGEN PODOFO_EXCEPTION_API(PODOFO_API)
210
211 /** The error handling class of the PoDoFo library.
212 * If a method encounters an error,
213 * a PdfError object is thrown as a C++ exception.
214 *
215 * This class does not inherit from std::exception.
216 *
217 * This class also provides meaningful error descriptions
218 * for the error codes which are values of the enum EPdfError,
219 * which are all codes PoDoFo uses (except the first and last one).
220 */
221 class PODOFO_EXCEPTION_API_DOXYGEN PdfError {
222 public:
223
224 // OC 17.08.2010 New to optionally replace stderr output by a callback:
225 class LogMessageCallback
226 {
227 public:
~LogMessageCallback()228 virtual ~LogMessageCallback() {} // every class with virtual methods needs a virtual destructor
229 virtual void LogMessage( ELogSeverity eLogSeverity, const char* pszPrefix, const char* pszMsg, va_list & args ) = 0;
230 virtual void LogMessage( ELogSeverity eLogSeverity, const wchar_t* pszPrefix, const wchar_t* pszMsg, va_list & args ) = 0;
231 };
232
233 /** Set a global static LogMessageCallback functor to replace stderr output in LogMessageInternal.
234 * \param fLogMessageCallback the pointer to the new callback functor object
235 * \returns the pointer to the previous callback functor object
236 */
237 static LogMessageCallback* SetLogMessageCallback(LogMessageCallback* fLogMessageCallback);
238
239 /** Create a PdfError object initialized to ePdfError_ErrOk.
240 */
241 PdfError();
242
243 /** Create a PdfError object with a given error code.
244 * \param eCode the error code of this object
245 * \param pszFile the file in which the error has occured.
246 * Use the compiler macro __FILE__ to initialize the field.
247 * \param line the line in which the error has occured.
248 * Use the compiler macro __LINE__ to initialize the field.
249 * \param pszInformation additional information on this error
250 */
251 PdfError( const EPdfError & eCode, const char* pszFile = NULL, int line = 0,
252 const char* pszInformation = NULL );
253
254 /** Create a PdfError object with a given error code.
255 * \param eCode the error code of this object
256 * \param pszFile the file in which the error has occured.
257 * Use the compiler macro __FILE__ to initialize the field.
258 * \param line the line in which the error has occured.
259 * Use the compiler macro __LINE__ to initialize the field.
260 * \param sInformation additional information on this error
261 */
262 explicit PdfError( const EPdfError & eCode, const char* pszFile, int line,
263 std::string sInformation );
264
265 /** Copy constructor
266 * \param rhs copy the contents of rhs into this object
267 */
268 PdfError( const PdfError & rhs );
269
270 virtual ~PdfError() throw();
271
272 /** Assignment operator
273 * \param rhs another PdfError object
274 * \returns this object
275 */
276 const PdfError & operator=( const PdfError & rhs );
277
278 /** Overloaded assignment operator
279 * \param eCode a EPdfError code
280 * \returns this object
281 */
282 const PdfError & operator=( const EPdfError & eCode );
283
284 /** Comparison operator, compares 2 PdfError objects
285 * \param rhs another PdfError object
286 * \returns true if both objects have the same error code.
287 */
288 bool operator==( const PdfError & rhs );
289
290 /** Overloaded comparison operator, compares this PdfError object
291 * with an error code
292 * \param eCode an error code (value of the enum EPdfError)
293 * \returns true if this object has the same error code.
294 */
295 bool operator==( const EPdfError & eCode );
296
297 /** Comparison operator, compares 2 PdfError objects
298 * \param rhs another PdfError object
299 * \returns true if the objects have different error codes.
300 */
301 bool operator!=( const PdfError & rhs );
302
303 /** Overloaded comparison operator, compares this PdfError object
304 * with an error code
305 * \param eCode an error code (value of the enum EPdfError)
306 * \returns true if this object has a different error code.
307 */
308 bool operator!=( const EPdfError & eCode );
309
310 /** Return the error code of this object.
311 * \returns the error code of this object
312 */
313 inline EPdfError GetError() const;
314
315 /** Get access to the internal callstack of this error.
316 * \returns the callstack deque of PdfErrorInfo objects.
317 */
318 inline const TDequeErrorInfo & GetCallstack() const;
319
320 /** Set the error code of this object.
321 * \param eCode the error code of this object
322 * \param pszFile the filename of the source file causing
323 * the error or NULL. Typically you will use
324 * the gcc macro __FILE__ here.
325 * \param line the line of source causing the error
326 * or 0. Typically you will use the gcc
327 * macro __LINE__ here.
328 * \param sInformation additional information on the error.
329 * e.g. how to fix the error. This string is intended to
330 * be shown to the user.
331 */
332 inline void SetError( const EPdfError & eCode, const char* pszFile, int line,
333 std::string sInformation );
334
335 /** Set the error code of this object.
336 * \param eCode the error code of this object
337 * \param pszFile the filename of the source file causing
338 * the error or NULL. Typically you will use
339 * the gcc macro __FILE__ here.
340 * \param line the line of source causing the error
341 * or 0. Typically you will use the gcc
342 * macro __LINE__ here.
343 * \param pszInformation additional information on the error,
344 * e.g. how to fix the error. This string is intended to
345 * be shown to the user.
346 */
347 inline void SetError( const EPdfError & eCode, const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL );
348
349 /** Set additional error information.
350 * \param pszInformation additional information on the error,
351 * e.g. how to fix the error. This string is intended to
352 * be shown to the user.
353 */
354 inline void SetErrorInformation( const char* pszInformation );
355
356 /** Set additional error information.
357 * \param pszInformation additional information on the error,
358 * e.g. how to fix the error. This string is intended to
359 * be shown to the user.
360 */
361 inline void SetErrorInformation( const wchar_t* pszInformation );
362
363 /** Add callstack information to an error object. Always call this function
364 * if you get an error object but do not handle the error but throw it again.
365 *
366 * \param pszFile the filename of the source file causing
367 * the error or NULL. Typically you will use
368 * the gcc macro __FILE__ here.
369 * \param line the line of source causing the error
370 * or 0. Typically you will use the gcc
371 * macro __LINE__ here.
372 * \param pszInformation additional information on the error,
373 * e.g. how to fix the error. This string is intended to
374 * be shown to the user.
375 */
376 inline void AddToCallstack( const char* pszFile = NULL, int line = 0, const char* pszInformation = NULL );
377
378 /** Add callstack information to an error object. Always call this function
379 * if you get an error object but do not handle the error but throw it again.
380 *
381 * \param pszFile the filename of the source file causing
382 * the error or NULL. Typically you will use
383 * the gcc macro __FILE__ here.
384 * \param line the line of source causing the error
385 * or 0. Typically you will use the gcc
386 * macro __LINE__ here.
387 * \param sInformation additional information on the error,
388 * e.g. how to fix the error. This string is intended to
389 * be shown to the user.
390 */
391 inline void AddToCallstack( const char* pszFile, int line, std::string sInformation );
392
393 /** \returns true if an error code was set
394 * and false if the error code is ePdfError_ErrOk.
395 */
396 inline bool IsError() const;
397
398 /** Print an error message to stderr. This includes callstack
399 * and extra info, if any of either was set.
400 */
401 void PrintErrorMsg() const;
402
403 /** Obtain error description.
404 * \returns a C string describing the error.
405 */
406 const char* what() const;
407
408 /** Get the name for a certain error code.
409 * \returns the name or NULL if no name for the specified
410 * error code is available.
411 */
412 PODOFO_NOTHROW static const char* ErrorName( EPdfError eCode );
413
414 /** Get the error message for a certain error code.
415 * \returns the error message or NULL if no error
416 * message for the specified error code
417 * is available.
418 */
419 static const char* ErrorMessage( EPdfError eCode );
420
421 /** Log a message to the logging system defined for PoDoFo.
422 * \param eLogSeverity the severity of the log message
423 * \param pszMsg the message to be logged
424 */
425 static void LogMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... );
426
427 /** Log a message to the logging system defined for PoDoFo.
428 * \param eLogSeverity the severity of the log message
429 * \param pszMsg the message to be logged
430 */
431 static void LogMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... );
432
433 /** Enable or disable logging.
434 * \param bEnable enable (true) or disable (false)
435 */
436 static void EnableLogging( bool bEnable );
437
438 /** Is the display of debugging messages enabled or not?
439 */
440 static bool LoggingEnabled();
441
442 /** Log a message to the logging system defined for PoDoFo for debugging.
443 * \param pszMsg the message to be logged
444 */
445 static void DebugMessage( const char* pszMsg, ... );
446
447 /** Enable or disable the display of debugging messages.
448 * \param bEnable enable (true) or disable (false)
449 */
450 static void EnableDebug( bool bEnable );
451
452 /** Is the display of debugging messages enabled or not?
453 */
454 static bool DebugEnabled();
455
456 private:
457 /** Log a message to the logging system defined for PoDoFo.
458 *
459 * This call does not check if logging is enabled and always
460 * prints the error message.
461 *
462 * \param eLogSeverity the severity of the log message
463 * \param pszMsg the message to be logged
464 */
465 static void LogErrorMessage( ELogSeverity eLogSeverity, const char* pszMsg, ... );
466
467 /** Log a message to the logging system defined for PoDoFo.
468 *
469 * This call does not check if logging is enabled and always
470 * prints the error message
471 *
472 * \param eLogSeverity the severity of the log message
473 * \param pszMsg the message to be logged
474 */
475 static void LogErrorMessage( ELogSeverity eLogSeverity, const wchar_t* pszMsg, ... );
476
477 static void LogMessageInternal( ELogSeverity eLogSeverity, const char* pszMsg, va_list & args );
478 static void LogMessageInternal( ELogSeverity eLogSeverity, const wchar_t* pszMsg, va_list & args );
479
480 private:
481 EPdfError m_error;
482
483 TDequeErrorInfo m_callStack;
484
485 static bool s_DgbEnabled;
486 static bool s_LogEnabled;
487
488 // OC 17.08.2010 New to optionally replace stderr output by a callback:
489 static LogMessageCallback* m_fLogMessageCallback;
490 };
491
492 // -----------------------------------------------------
493 //
494 // -----------------------------------------------------
GetError()495 EPdfError PdfError::GetError() const
496 {
497 return m_error;
498 }
499
500 // -----------------------------------------------------
501 //
502 // -----------------------------------------------------
GetCallstack()503 const TDequeErrorInfo & PdfError::GetCallstack() const
504 {
505 return m_callStack;
506 }
507
508 // -----------------------------------------------------
509 //
510 // -----------------------------------------------------
SetError(const EPdfError & eCode,const char * pszFile,int line,const char * pszInformation)511 void PdfError::SetError( const EPdfError & eCode, const char* pszFile, int line, const char* pszInformation )
512 {
513 m_error = eCode;
514 this->AddToCallstack( pszFile, line, pszInformation );
515 }
516
517 // -----------------------------------------------------
518 //
519 // -----------------------------------------------------
AddToCallstack(const char * pszFile,int line,const char * pszInformation)520 void PdfError::AddToCallstack( const char* pszFile, int line, const char* pszInformation )
521 {
522 m_callStack.push_front( PdfErrorInfo( line, pszFile, pszInformation ) );
523 }
524
525 // -----------------------------------------------------
526 //
527 // -----------------------------------------------------
SetError(const EPdfError & eCode,const char * pszFile,int line,std::string sInformation)528 void PdfError::SetError( const EPdfError & eCode, const char* pszFile, int line, std::string sInformation )
529 {
530 m_error = eCode;
531 this->AddToCallstack( pszFile, line, sInformation );
532 }
533
534 // -----------------------------------------------------
535 //
536 // -----------------------------------------------------
AddToCallstack(const char * pszFile,int line,std::string sInformation)537 void PdfError::AddToCallstack( const char* pszFile, int line, std::string sInformation )
538 {
539 m_callStack.push_front( PdfErrorInfo( line, pszFile, sInformation ) );
540 }
541 // -----------------------------------------------------
542 //
543 // -----------------------------------------------------
SetErrorInformation(const char * pszInformation)544 void PdfError::SetErrorInformation( const char* pszInformation )
545 {
546 if( m_callStack.size() )
547 m_callStack.front().SetInformation( pszInformation ? pszInformation : "" );
548 }
549
550 // -----------------------------------------------------
551 //
552 // -----------------------------------------------------
SetErrorInformation(const wchar_t * pszInformation)553 void PdfError::SetErrorInformation( const wchar_t* pszInformation )
554 {
555 if( m_callStack.size() )
556 m_callStack.front().SetInformation( pszInformation ? pszInformation : L"" );
557 }
558
559 // -----------------------------------------------------
560 //
561 // -----------------------------------------------------
IsError()562 bool PdfError::IsError() const
563 {
564 return (m_error != ePdfError_ErrOk);
565 }
566
567 };
568
569 #endif /* _PDF_ERROR_H_ */
570
571
572
573