Commit message: Fix crash on missing embedded file

Check whether an embedded file is actually present in the PDF
and show warning in that case.

https://bugs.freedesktop.org/show_bug.cgi?id=106137
https://gitlab.freedesktop.org/poppler/poppler/issues/236
CVE: CVE-2018-19149
CWE: CWE-476
Vulnerability description: Poppler before 0.70.0 has a NULL pointer dereference in _poppler_attachment_new when called from poppler_annot_file_attachment_get_attachment.

Project: poppler

poppler_fonts_iter_get_encoding (PopplerFontsIter *iter)
{
	GooString *encoding;
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	encoding = info->getEncoding();
	if (encoding != nullptr) {
		return encoding->getCString();
	} else {
		return nullptr;
	}
}

Project: poppler

poppler_fonts_iter_get_name (PopplerFontsIter *iter)
{
	FontInfo *info;
	const char *name;

	name = poppler_fonts_iter_get_full_name (iter);
	info = (FontInfo *)iter->items->get (iter->index);

	if (info->getSubset() && name) {
		while (*name && *name != '+')
			name++;

		if (*name)
			name++;
	}

	return name;
}

Project: poppler

poppler_document_get_page_layout (PopplerDocument *document)
{
  Catalog *catalog;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), POPPLER_PAGE_LAYOUT_UNSET);

  catalog = document->doc->getCatalog ();
  if (catalog && catalog->isOk ())
    return convert_page_layout (catalog->getPageLayout ());

  return POPPLER_PAGE_LAYOUT_UNSET;
}

Project: poppler

poppler_document_get_modification_date (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), (time_t)-1);

  GooString *str = document->doc->getDocInfoModDate();
  if (str == nullptr) {
    return (time_t)-1;
  }

  time_t date;
  gboolean success = _poppler_convert_pdf_date_to_gtime (str, &date);
  delete str;

  return (success) ? date : (time_t)-1;
}

Project: poppler

poppler_document_get_creation_date (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), (time_t)-1);

  GooString *str = document->doc->getDocInfoCreatDate();
  if (str == nullptr) {
    return (time_t)-1;
  }

  time_t date;
  gboolean success = _poppler_convert_pdf_date_to_gtime (str, &date);
  delete str;

  return (success) ? date : (time_t)-1;
}

Project: poppler

poppler_document_get_attachments (PopplerDocument *document)
{
  Catalog *catalog;
  int n_files, i;
  GList *retval = nullptr;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  catalog = document->doc->getCatalog ();
  if (catalog == nullptr || ! catalog->isOk ())
    return nullptr;

  n_files = catalog->numEmbeddedFiles ();
  for (i = 0; i < n_files; i++)
    {
      PopplerAttachment *attachment;
      FileSpec *emb_file;

      emb_file = catalog->embeddedFile (i);
      if (!emb_file->isOk () || !emb_file->getEmbeddedFile()->isOk()) {
        delete emb_file;
	continue;
      }

      attachment = _poppler_attachment_new (emb_file);
      delete emb_file;

      if (attachment != NULL)
        retval = g_list_prepend (retval, attachment);
    }
  return g_list_reverse (retval);
}

Project: poppler

poppler_document_get_n_pages (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), 0);

  return document->doc->getNumPages();
}

Project: poppler

poppler_document_save_a_copy (PopplerDocument  *document,
			      const char       *uri,
			      GError          **error)
{
  char *filename;
  gboolean retval = FALSE;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), FALSE);

  filename = g_filename_from_uri (uri, nullptr, error);
  if (filename != nullptr) {
    GooString *fname = new GooString (filename);
    int err_code;
    g_free (filename);

    err_code = document->doc->saveWithoutChangesAs (fname);
    retval = handle_save_error (err_code, error);
    delete fname;
  }

  return retval;
}

Project: poppler

poppler_document_set_property (GObject      *object,
			       guint         prop_id,
			       const GValue *value,
			       GParamSpec   *pspec)
{
  PopplerDocument *document = POPPLER_DOCUMENT (object);

  switch (prop_id)
    {
    case PROP_TITLE:
      poppler_document_set_title (document, g_value_get_string (value));
      break;
    case PROP_AUTHOR:
      poppler_document_set_author (document, g_value_get_string (value));
      break;
    case PROP_SUBJECT:
      poppler_document_set_subject (document, g_value_get_string (value));
      break;
    case PROP_KEYWORDS:
      poppler_document_set_keywords (document, g_value_get_string (value));
      break;
    case PROP_CREATOR:
      poppler_document_set_creator (document, g_value_get_string (value));
      break;
    case PROP_PRODUCER:
      poppler_document_set_producer (document, g_value_get_string (value));
      break;
    case PROP_CREATION_DATE:
      poppler_document_set_creation_date (document, g_value_get_int (value));
      break;
    case PROP_MOD_DATE:
      poppler_document_set_modification_date (document, g_value_get_int (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

Project: poppler

poppler_document_get_n_attachments (PopplerDocument *document)
{
  Catalog *catalog;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), 0);

  catalog = document->doc->getCatalog ();

  return catalog && catalog->isOk () ? catalog->numEmbeddedFiles () : 0;
}

Project: poppler

poppler_ps_file_set_paper_size (PopplerPSFile *ps_file,
                                double width, double height)
{
        g_return_if_fail (ps_file->out == nullptr);
        
        ps_file->paper_width = width;
        ps_file->paper_height = height;
}

Project: poppler

poppler_index_iter_next (PopplerIndexIter *iter)
{
	g_return_val_if_fail (iter != nullptr, FALSE);

	iter->index++;
	if (iter->index >= iter->items->getLength())
		return FALSE;

	return TRUE;
}

Project: poppler

poppler_ps_file_new (PopplerDocument *document, const char *filename,
		     int first_page, int n_pages)
{
	PopplerPSFile *ps_file;

	g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
	g_return_val_if_fail (filename != nullptr, NULL);
	g_return_val_if_fail (n_pages > 0, NULL);

        ps_file = (PopplerPSFile *) g_object_new (POPPLER_TYPE_PS_FILE, nullptr);
	ps_file->document = (PopplerDocument *) g_object_ref (document);
        ps_file->filename = g_strdup (filename);
        ps_file->first_page = first_page + 1;
        ps_file->last_page = first_page + 1 + n_pages - 1;

	return ps_file;
}

Project: poppler

poppler_attachment_save_to_callback (PopplerAttachment          *attachment,
				     PopplerAttachmentSaveFunc   save_func,
				     gpointer                    user_data,
				     GError                    **error)
{
  Stream *stream;
  gchar buf[BUF_SIZE]; 
  int i;
  gboolean eof_reached = FALSE;

  g_return_val_if_fail (POPPLER_IS_ATTACHMENT (attachment), FALSE);

  stream = POPPLER_ATTACHMENT_GET_PRIVATE (attachment)->obj_stream.getStream();
  stream->reset();

  do
    {
      int data;

      for (i = 0; i < BUF_SIZE; i++)
	{
	  data = stream->getChar ();
	  if (data == EOF)
	    {
	      eof_reached = TRUE;
	      break;
	    }
	  buf[i] = data;
	}

      if (i > 0)
	{
	  if (! (save_func) (buf, i, user_data, error))
	    return FALSE;
	}
    }
  while (! eof_reached);


  return TRUE;
}

Project: poppler

poppler_index_iter_free (PopplerIndexIter *iter)
{
	if (G_UNLIKELY (iter == nullptr))
		return;

	g_object_unref (iter->document);
	g_slice_free (PopplerIndexIter, iter);
}

Project: poppler

poppler_document_get_creator (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_creator = document->doc->getDocInfoCreator();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_creator);
  delete goo_creator;

  return utf8;
}

Project: poppler

poppler_layers_iter_get_layer (PopplerLayersIter *iter)
{
  Layer *layer;
  PopplerLayer *poppler_layer = nullptr;
  
  g_return_val_if_fail (iter != nullptr, NULL);
  
  layer = (Layer *)g_list_nth_data (iter->items, iter->index);
  if (layer->oc) {
    GList *rb_group = nullptr;

    rb_group = _poppler_document_get_layer_rbgroup (iter->document, layer);
    poppler_layer = _poppler_layer_new (iter->document, layer, rb_group);
  }
  
  return poppler_layer;
}

Project: poppler

poppler_font_info_new (PopplerDocument *document)
{
	PopplerFontInfo *font_info;

	g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

	font_info = (PopplerFontInfo *) g_object_new (POPPLER_TYPE_FONT_INFO,
						      nullptr);
	font_info->document = (PopplerDocument *) g_object_ref (document);
	font_info->scanner = new FontInfoScanner(document->doc);

	return font_info;
}

Project: poppler

poppler_document_get_keywords (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_keywords = document->doc->getDocInfoKeywords();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_keywords);
  delete goo_keywords;

  return utf8;
}

Project: poppler

poppler_document_get_id (PopplerDocument *document,
			 gchar          **permanent_id,
			 gchar          **update_id)
{
  GooString permanent;
  GooString update;
  gboolean  retval = FALSE;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), FALSE);

  if (permanent_id)
    *permanent_id = nullptr;
  if (update_id)
    *update_id = nullptr;

  if (document->doc->getID (permanent_id ? &permanent : nullptr, update_id ? &update : nullptr)) {
    if (permanent_id)
      *permanent_id = (gchar *)g_memdup (permanent.getCString(), 32);
    if (update_id)
      *update_id = (gchar *)g_memdup (update.getCString(), 32);

    retval = TRUE;
  }

  return retval;
}

Project: poppler

poppler_document_class_init (PopplerDocumentClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = poppler_document_finalize;
  gobject_class->get_property = poppler_document_get_property;
  gobject_class->set_property = poppler_document_set_property;

  /**
   * PopplerDocument:title:
   *
   * The document's title or %NULL
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_TITLE,
				   g_param_spec_string ("title",
							"Document Title",
							"The title of the document",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:format:
   *
   * The PDF version as string. See also poppler_document_get_pdf_version_string()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_FORMAT,
				   g_param_spec_string ("format",
							"PDF Format",
							"The PDF version of the document",
							nullptr,
							G_PARAM_READABLE));

  /**
   * PopplerDocument:format-major:
   *
   * The PDF major version number. See also poppler_document_get_pdf_version()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_FORMAT_MAJOR,
				   g_param_spec_uint ("format-major",
						      "PDF Format Major",
						      "The PDF major version number of the document",
						      0, G_MAXUINT, 1,
						      G_PARAM_READABLE));

  /**
   * PopplerDocument:format-minor:
   *
   * The PDF minor version number. See also poppler_document_get_pdf_version()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_FORMAT_MINOR,
				   g_param_spec_uint ("format-minor",
						      "PDF Format Minor",
						      "The PDF minor version number of the document",
						      0, G_MAXUINT, 0,
						      G_PARAM_READABLE));

  /**
   * PopplerDocument:author:
   *
   * The author of the document
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_AUTHOR,
				   g_param_spec_string ("author",
							"Author",
							"The author of the document",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:subject:
   *
   * The subject of the document
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_SUBJECT,
				   g_param_spec_string ("subject",
							"Subject",
							"Subjects the document touches",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:keywords:
   *
   * The keywords associated to the document
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_KEYWORDS,
				   g_param_spec_string ("keywords",
							"Keywords",
							"Keywords",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:creator:
   *
   * The creator of the document. See also poppler_document_get_creator()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_CREATOR,
				   g_param_spec_string ("creator",
							"Creator",
							"The software that created the document",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:producer:
   *
   * The producer of the document. See also poppler_document_get_producer()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_PRODUCER,
				   g_param_spec_string ("producer",
							"Producer",
							"The software that converted the document",
							nullptr,
							G_PARAM_READWRITE));

  /**
   * PopplerDocument:creation-date:
   *
   * The date the document was created as seconds since the Epoch, or -1
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_CREATION_DATE,
				   g_param_spec_int ("creation-date",
						     "Creation Date",
						     "The date and time the document was created",
						     -1, G_MAXINT, -1,
						     G_PARAM_READWRITE));

  /**
   * PopplerDocument:mod-date:
   *
   * The date the document was most recently modified as seconds since the Epoch, or -1
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_MOD_DATE,
				   g_param_spec_int ("mod-date",
						     "Modification Date",
						     "The date and time the document was modified",
						     -1, G_MAXINT, -1,
						     G_PARAM_READWRITE));

  /**
   * PopplerDocument:linearized:
   *
   * Whether document is linearized. See also poppler_document_is_linearized()
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_LINEARIZED,
				   g_param_spec_boolean ("linearized",
							 "Fast Web View Enabled",
							 "Is the document optimized for web viewing?",
							 FALSE,
							 G_PARAM_READABLE));

  /**
   * PopplerDocument:page-layout:
   *
   * The page layout that should be used when the document is opened
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_PAGE_LAYOUT,
				   g_param_spec_enum ("page-layout",
						      "Page Layout",
						      "Initial Page Layout",
						      POPPLER_TYPE_PAGE_LAYOUT,
						      POPPLER_PAGE_LAYOUT_UNSET,
						      G_PARAM_READABLE));

  /**
   * PopplerDocument:page-mode:
   *
   * The mode that should be used when the document is opened
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_PAGE_MODE,
				   g_param_spec_enum ("page-mode",
						      "Page Mode",
						      "Page Mode",
						      POPPLER_TYPE_PAGE_MODE,
						      POPPLER_PAGE_MODE_UNSET,
						      G_PARAM_READABLE));

  /**
   * PopplerDocument:viewer-preferences:
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_VIEWER_PREFERENCES,
				   g_param_spec_flags ("viewer-preferences",
						       "Viewer Preferences",
						       "Viewer Preferences",
						       POPPLER_TYPE_VIEWER_PREFERENCES,
						       POPPLER_VIEWER_PREFERENCES_UNSET,
						       G_PARAM_READABLE));

  /**
   * PopplerDocument:permissions:
   *
   * Flags specifying which operations are permitted when the document is opened
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_PERMISSIONS,
				   g_param_spec_flags ("permissions",
						       "Permissions",
						       "Permissions",
						       POPPLER_TYPE_PERMISSIONS,
						       POPPLER_PERMISSIONS_FULL,
						       G_PARAM_READABLE));

  /**
   * PopplerDocument:metadata:
   *
   * Document metadata in XML format, or %NULL
   */
  g_object_class_install_property (G_OBJECT_CLASS (klass),
				   PROP_METADATA,
				   g_param_spec_string ("metadata",
							"XML Metadata",
							"Embedded XML metadata",
							nullptr,
							G_PARAM_READABLE));
}

Project: poppler

poppler_index_iter_get_child (PopplerIndexIter *parent)
{
	PopplerIndexIter *child;
	OutlineItem *item;

	g_return_val_if_fail (parent != nullptr, NULL);
	
	item = (OutlineItem *)parent->items->get (parent->index);
	item->open ();
	if (! (item->hasKids() && item->getKids()) )
		return nullptr;

	child = g_slice_new0 (PopplerIndexIter);
	child->document = (PopplerDocument *)g_object_ref (parent->document);
	child->items = item->getKids ();

	g_assert (child->items);

	return child;
}

Project: poppler

poppler_index_iter_get_action (PopplerIndexIter  *iter)
{
	OutlineItem *item;
	const LinkAction *link_action;
	PopplerAction *action;
	gchar *title;

	g_return_val_if_fail (iter != nullptr, NULL);

	item = (OutlineItem *)iter->items->get (iter->index);
	link_action = item->getAction ();

	title = unicode_to_char (item->getTitle(),
				 item->getTitleLength ());

	action = _poppler_action_new (iter->document, link_action, title);
	g_free (title);

	return action;
}

Project: poppler

poppler_fonts_iter_copy (PopplerFontsIter *iter)
{
	PopplerFontsIter *new_iter;

	g_return_val_if_fail (iter != nullptr, NULL);

	new_iter = g_slice_dup (PopplerFontsIter, iter);

	new_iter->items = new GooList ();
	for (int i = 0; i < iter->items->getLength(); i++) {
		FontInfo *info = (FontInfo *)iter->items->get(i);
		new_iter->items->push_back (new FontInfo (*info));
	}

	return new_iter;
}

Project: poppler

get_optional_content_items (OCGs *ocg)
{
  Array *order;
  GList *items = nullptr;
  
  order = ocg->getOrderArray ();

  if (order) {
    items = get_optional_content_items_sorted (ocg, nullptr, order);
  } else {
    const auto &ocgs = ocg->getOCGs ();

    for (const auto &oc : ocgs) {
      Layer *layer = layer_new (oc.second.get());

      items = g_list_prepend (items, layer);
    }
    
    items = g_list_reverse (items);
  }

  return items;
}

Project: poppler

poppler_document_set_creator (PopplerDocument *document, const gchar *creator)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_creator;
  if (!creator) {
    goo_creator = nullptr;
  } else {
    goo_creator = _poppler_goo_string_from_utf8(creator);
    if (!goo_creator)
      return;
  }
  document->doc->setDocInfoCreator(goo_creator);
}

Project: poppler

poppler_document_new_from_stream (GInputStream *stream,
                                  goffset       length,
                                  const char   *password,
                                  GCancellable *cancellable,
                                  GError      **error)
{
  PDFDoc *newDoc;
  BaseStream *str;
  GooString *password_g;

  g_return_val_if_fail(G_IS_INPUT_STREAM(stream), NULL);
  g_return_val_if_fail(length == (goffset)-1 || length > 0, NULL);

  if (!globalParams) {
    globalParams = new GlobalParams();
  }

  if (!G_IS_SEEKABLE(stream) || !g_seekable_can_seek(G_SEEKABLE(stream))) {
    g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
                        "Stream is not seekable");
    return nullptr;
  }

  if (stream_is_memory_buffer_or_local_file(stream)) {
    str = new PopplerInputStream(stream, cancellable, 0, gFalse, 0, Object(objNull));
  } else {
    CachedFile *cachedFile = new CachedFile(new PopplerCachedFileLoader(stream, cancellable, length), new GooString());
    str = new CachedFileStream(cachedFile, 0, gFalse, cachedFile->getLength(), Object(objNull));
  }

  password_g = poppler_password_to_latin1(password);
  newDoc = new PDFDoc(str, password_g, password_g);
  delete password_g;

  return _poppler_document_new_from_pdfdoc (newDoc, error);
}

Project: poppler

poppler_layers_iter_get_child (PopplerLayersIter *parent)
{
  PopplerLayersIter *child;
  Layer *layer;

  g_return_val_if_fail (parent != nullptr, NULL);
	
  layer = (Layer *) g_list_nth_data (parent->items, parent->index);
  if (!layer || !layer->kids)
    return nullptr;

  child = g_slice_new0 (PopplerLayersIter);
  child->document = (PopplerDocument *)g_object_ref (parent->document);
  child->items = layer->kids;

  g_assert (child->items);

  return child;
}

Project: poppler

poppler_document_get_pdf_version_string (PopplerDocument *document)
{
  gchar *retval;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  retval = g_strndup ("PDF-", 15); /* allocates 16 chars, pads with \0s */
  g_ascii_formatd (retval + 4, 15 + 1 - 4, "%.2g",
		   document->doc->getPDFMajorVersion () + document->doc->getPDFMinorVersion() / 10.0);
  return retval;
}

Project: poppler

char *_poppler_goo_string_to_utf8(const GooString *s)
{
  if (s == nullptr) {
    return nullptr;
  }

  char *result;

  if (s->hasUnicodeMarker()) {
    result = g_convert (s->getCString () + 2,
			s->getLength () - 2,
			"UTF-8", "UTF-16BE", nullptr, nullptr, nullptr);
  } else {
    int len;
    gunichar *ucs4_temp;
    int i;
    
    len = s->getLength ();
    ucs4_temp = g_new (gunichar, len + 1);
    for (i = 0; i < len; ++i) {
      ucs4_temp[i] = pdfDocEncoding[(unsigned char)s->getChar(i)];
    }
    ucs4_temp[i] = 0;

    result = g_ucs4_to_utf8 (ucs4_temp, -1, nullptr, nullptr, nullptr);

    g_free (ucs4_temp);
  }

  return result;
}

Project: poppler

poppler_document_get_pdf_version (PopplerDocument *document,
				  guint           *major_version,
				  guint           *minor_version)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  if (major_version)
    *major_version = document->doc->getPDFMajorVersion ();
  if (minor_version)
    *minor_version = document->doc->getPDFMinorVersion();
}

Project: poppler

poppler_ps_file_finalize (GObject *object)
{
        PopplerPSFile *ps_file = POPPLER_PS_FILE (object);

        delete ps_file->out;
        g_object_unref (ps_file->document);
        g_free (ps_file->filename);

        G_OBJECT_CLASS (poppler_ps_file_parent_class)->finalize (object);
}

Project: poppler

poppler_document_get_author (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_author = document->doc->getDocInfoAuthor();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_author);
  delete goo_author;

  return utf8;
}

Project: poppler

poppler_attachment_save (PopplerAttachment  *attachment,
			 const char         *filename,
			 GError            **error)
{
  gboolean result;
  FILE *f;
  
  g_return_val_if_fail (POPPLER_IS_ATTACHMENT (attachment), FALSE);

  f = g_fopen (filename, "wb");

  if (f == nullptr)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   _("Failed to open '%s' for writing: %s"),
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  result = poppler_attachment_save_to_callback (attachment, save_helper, f, error);

  if (fclose (f) < 0)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   _("Failed to close '%s', all data may not have been saved: %s"),
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  return result;
}

Project: poppler

poppler_document_get_subject (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_subject = document->doc->getDocInfoSubject();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_subject);
  delete goo_subject;

  return utf8;
}

Project: poppler

poppler_ps_file_class_init (PopplerPSFileClass *klass)
{
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

        gobject_class->finalize = poppler_ps_file_finalize;
}

Project: poppler

_poppler_goo_string_from_utf8(const gchar *src)
{
  if (src == nullptr) {
    return nullptr;
  }

  gsize outlen;

  gchar *utf16 = g_convert (src, -1, "UTF-16BE", "UTF-8", nullptr, &outlen, nullptr);
  if (utf16 == nullptr) {
    return nullptr;
  }

  GooString *result = new GooString (utf16, outlen);
  g_free (utf16);

  if (!result->hasUnicodeMarker()) {
    result->prependUnicodeMarker();
  }

  return result;
}

Project: poppler

poppler_document_get_metadata (PopplerDocument *document)
{
  Catalog *catalog;
  gchar *retval = nullptr;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  catalog = document->doc->getCatalog ();
  if (catalog && catalog->isOk ()) {
    GooString *s = catalog->readMetadata ();

    if (s != nullptr) {
      retval = g_strdup (s->getCString());
      delete s;
    }
  }

  return retval;
}

Project: poppler

poppler_layers_iter_copy (PopplerLayersIter *iter)
{
  PopplerLayersIter *new_iter;

  g_return_val_if_fail (iter != nullptr, NULL);
  
  new_iter = g_slice_dup (PopplerLayersIter, iter);
  new_iter->document = (PopplerDocument *) g_object_ref (new_iter->document);
  
  return new_iter;
}

Project: poppler

poppler_document_layers_free (PopplerDocument *document)
{
  if (G_UNLIKELY (!document->layers))
    return;

  g_list_foreach (document->layers, (GFunc)layer_free, nullptr);
  g_list_free (document->layers);

  g_list_foreach (document->layers_rbgroups, (GFunc)g_list_free, nullptr);
  g_list_free (document->layers_rbgroups);

  document->layers = nullptr;
  document->layers_rbgroups = nullptr;
}

Project: poppler

poppler_fonts_iter_get_file_name (PopplerFontsIter *iter)
{
	GooString *file;
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	file = info->getFile();
	if (file != nullptr) {
		return file->getCString();
	} else {
		return nullptr;
	}
}

Project: poppler

poppler_fonts_iter_get_full_name (PopplerFontsIter *iter)
{
	GooString *name;
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	name = info->getName();
	if (name != nullptr) {
		return info->getName()->getCString();
	} else {
		return nullptr;
	}
}

Project: poppler

_poppler_document_new_from_pdfdoc (PDFDoc  *newDoc,
                                   GError **error)
{
  PopplerDocument *document;

  if (!newDoc->isOk()) {
    int fopen_errno;
    switch (newDoc->getErrorCode())
      {
      case errOpenFile:
        // If there was an error opening the file, count it as a G_FILE_ERROR 
        // and set the GError parameters accordingly. (this assumes that the 
        // only way to get an errOpenFile error is if newDoc was created using 
        // a filename and thus fopen was called, which right now is true.
        fopen_errno = newDoc->getFopenErrno();
        g_set_error (error, G_FILE_ERROR,
		     g_file_error_from_errno (fopen_errno),
		     "%s", g_strerror (fopen_errno));
	break;
      case errBadCatalog:
        g_set_error (error, POPPLER_ERROR,
		     POPPLER_ERROR_BAD_CATALOG,
		     "Failed to read the document catalog");
	break;
      case errDamaged:
        g_set_error (error, POPPLER_ERROR,
		     POPPLER_ERROR_DAMAGED,
		     "PDF document is damaged");
	break;
      case errEncrypted:
        g_set_error (error, POPPLER_ERROR,
		     POPPLER_ERROR_ENCRYPTED,
		     "Document is encrypted");
	break;
      default:
        g_set_error (error, POPPLER_ERROR,
		     POPPLER_ERROR_INVALID,
		     "Failed to load document");
    }
    
    delete newDoc;
    return nullptr;
  }

  document = (PopplerDocument *) g_object_new (POPPLER_TYPE_DOCUMENT, nullptr);
  document->doc = newDoc;

  document->output_dev = new CairoOutputDev ();
  document->output_dev->startDoc(document->doc);

  return document;
}

Project: poppler

poppler_document_set_title (PopplerDocument *document, const gchar *title)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_title;
  if (!title) {
    goo_title = nullptr;
  } else {
    goo_title = _poppler_goo_string_from_utf8(title);
    if (!goo_title)
      return;
  }
  document->doc->setDocInfoTitle(goo_title);
}

Project: poppler

poppler_index_iter_new (PopplerDocument *document)
{
	PopplerIndexIter *iter;
	Outline *outline;
	const GooList *items;

	outline = document->doc->getOutline();
	if (outline == nullptr)
		return nullptr;

	items = outline->getItems();
	if (items == nullptr)
		return nullptr;

	iter = g_slice_new (PopplerIndexIter);
	iter->document = (PopplerDocument *) g_object_ref (document);
	iter->items = items;
	iter->index = 0;

	return iter;
}

Project: poppler

poppler_font_info_init (PopplerFontInfo *font_info)
{
        font_info->document = nullptr;
        font_info->scanner = nullptr;
}

Project: poppler

_poppler_convert_pdf_date_to_gtime (const GooString *date,
				    time_t    *gdate) 
{
  gchar *date_string;
  gboolean retval;

  if (date->hasUnicodeMarker()) {
    date_string = g_convert (date->getCString () + 2,
			     date->getLength () - 2,
			     "UTF-8", "UTF-16BE", nullptr, nullptr, nullptr);		
  } else {
    date_string = g_strndup (date->getCString (), date->getLength ());
  }

  retval = poppler_date_parse (date_string, gdate);
  g_free (date_string);

  return retval;
}

Project: poppler

poppler_document_is_linearized (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), FALSE);

  return document->doc->isLinearized ();
}

Project: poppler

poppler_document_get_property (GObject    *object,
			       guint       prop_id,
			       GValue     *value,
			       GParamSpec *pspec)
{
  PopplerDocument *document = POPPLER_DOCUMENT (object);
  guint version;

  switch (prop_id)
    {
    case PROP_TITLE:
      g_value_take_string (value, poppler_document_get_title (document));
      break;
    case PROP_FORMAT:
      g_value_take_string (value, poppler_document_get_pdf_version_string (document));
      break;
    case PROP_FORMAT_MAJOR:
      poppler_document_get_pdf_version (document, &version, nullptr);
      g_value_set_uint (value, version);
      break;
    case PROP_FORMAT_MINOR:
      poppler_document_get_pdf_version (document, nullptr, &version);
      g_value_set_uint (value, version);
      break;
    case PROP_AUTHOR:
      g_value_take_string (value, poppler_document_get_author (document));
      break;
    case PROP_SUBJECT:
      g_value_take_string (value, poppler_document_get_subject (document));
      break;
    case PROP_KEYWORDS:
      g_value_take_string (value, poppler_document_get_keywords (document));
      break;
    case PROP_CREATOR:
      g_value_take_string (value, poppler_document_get_creator (document));
      break;
    case PROP_PRODUCER:
      g_value_take_string (value, poppler_document_get_producer (document));
      break;
    case PROP_CREATION_DATE:
      g_value_set_int (value, poppler_document_get_creation_date (document));
      break;
    case PROP_MOD_DATE:
      g_value_set_int (value, poppler_document_get_modification_date (document));
      break;
    case PROP_LINEARIZED:
      g_value_set_boolean (value, poppler_document_is_linearized (document));
      break;
    case PROP_PAGE_LAYOUT:
      g_value_set_enum (value, poppler_document_get_page_layout (document));
      break;
    case PROP_PAGE_MODE:
      g_value_set_enum (value, poppler_document_get_page_mode (document));
      break;
    case PROP_VIEWER_PREFERENCES:
      /* FIXME: write... */
      g_value_set_flags (value, POPPLER_VIEWER_PREFERENCES_UNSET);
      break;
    case PROP_PERMISSIONS:
      g_value_set_flags (value, poppler_document_get_permissions (document));
      break;
    case PROP_METADATA:
      g_value_take_string (value, poppler_document_get_metadata (document));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

Project: poppler

poppler_fonts_iter_is_embedded (PopplerFontsIter *iter)
{
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	return info->getEmbedded();
}

Project: poppler

poppler_document_save (PopplerDocument  *document,
		       const char       *uri,
		       GError          **error)
{
  char *filename;
  gboolean retval = FALSE;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), FALSE);

  filename = g_filename_from_uri (uri, nullptr, error);
  if (filename != nullptr) {
    GooString *fname = new GooString (filename);
    int err_code;
    g_free (filename);

    err_code = document->doc->saveAs (fname);
    retval = handle_save_error (err_code, error);
    delete fname;
  }

  return retval;
}

Project: poppler

poppler_document_finalize (GObject *object)
{
  PopplerDocument *document = POPPLER_DOCUMENT (object);

  poppler_document_layers_free (document);
  delete document->output_dev;
  delete document->doc;

  G_OBJECT_CLASS (poppler_document_parent_class)->finalize (object);
}

Project: poppler

poppler_document_get_page (PopplerDocument  *document,
			   int               index)
{
  Page *page;

  g_return_val_if_fail (0 <= index &&
			index < poppler_document_get_n_pages (document),
			NULL);

  page = document->doc->getPage (index + 1);
  if (!page) return nullptr;

  return _poppler_page_new (document, page, index);
}

Project: poppler

poppler_index_iter_is_open (PopplerIndexIter *iter)
{
	OutlineItem *item;

	item = (OutlineItem *)iter->items->get (iter->index);

	return item->isOpen();
}

Project: poppler

get_optional_content_items_sorted (OCGs *ocg, Layer *parent, Array *order)
{
  GList *items = nullptr;
  Layer *last_item = parent;
  int i;

  for (i = 0; i < order->getLength (); ++i) {
    Object orderItem = order->get (i);

    if (orderItem.isDict ()) {
      Object ref = order->getNF (i);
      if (ref.isRef ()) {
        OptionalContentGroup *oc = ocg->findOcgByRef (ref.getRef ());
	Layer *layer = layer_new (oc);

	items = g_list_prepend (items, layer);
	last_item = layer;
      }
    } else if (orderItem.isArray () && orderItem.arrayGetLength () > 0) {
      if (!last_item) {
        last_item = layer_new (nullptr);
	items = g_list_prepend (items, last_item);
      }
      last_item->kids = get_optional_content_items_sorted (ocg, last_item, orderItem.getArray ());
      last_item = nullptr;
    } else if (orderItem.isString ()) {
      last_item->label = _poppler_goo_string_to_utf8 (orderItem.getString ());
    }
  }
  
  return g_list_reverse (items);
}

Project: poppler

poppler_document_set_producer (PopplerDocument *document, const gchar *producer)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_producer;
  if (!producer) {
    goo_producer = nullptr;
  } else {
    goo_producer = _poppler_goo_string_from_utf8(producer);
    if (!goo_producer)
      return;
  }
  document->doc->setDocInfoProducer(goo_producer);
}

Project: poppler

poppler_fonts_iter_get_font_type (PopplerFontsIter *iter)
{
	FontInfo *info;

	g_return_val_if_fail (iter != nullptr, POPPLER_FONT_TYPE_UNKNOWN);

	info = (FontInfo *)iter->items->get (iter->index);

	return (PopplerFontType)info->getType ();
}

Project: poppler

poppler_document_set_modification_date (PopplerDocument *document,
                                        time_t modification_date)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *str = modification_date == (time_t)-1 ? nullptr : timeToDateString (&modification_date);
  document->doc->setDocInfoModDate (str);
}

Project: poppler

poppler_document_get_title (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_title = document->doc->getDocInfoTitle();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_title);
  delete goo_title;

  return utf8;
}

Project: poppler

poppler_fonts_iter_is_subset (PopplerFontsIter *iter)
{
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	return info->getSubset();
}

Project: poppler

poppler_ps_file_free (PopplerPSFile *ps_file)
{
	g_return_if_fail (ps_file != nullptr);
        g_object_unref (ps_file);
}

Project: poppler

poppler_fonts_iter_new (GooList *items)
{
	PopplerFontsIter *iter;

	iter = g_slice_new (PopplerFontsIter);
	iter->items = items;
	iter->index = 0;

	return iter;
}

Project: poppler

stream_is_memory_buffer_or_local_file (GInputStream *stream)
{
  return G_IS_MEMORY_INPUT_STREAM(stream) ||
    (G_IS_FILE_INPUT_STREAM(stream) && strcmp(g_type_name_from_instance((GTypeInstance*)stream), "GLocalFileInputStream") == 0);
}

Project: poppler

poppler_document_get_permissions (PopplerDocument *document)
{
  guint flag = 0;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), POPPLER_PERMISSIONS_FULL);

  if (document->doc->okToPrint ())
    flag |= POPPLER_PERMISSIONS_OK_TO_PRINT;
  if (document->doc->okToChange ())
    flag |= POPPLER_PERMISSIONS_OK_TO_MODIFY;
  if (document->doc->okToCopy ())
    flag |= POPPLER_PERMISSIONS_OK_TO_COPY;
  if (document->doc->okToAddNotes ())
    flag |= POPPLER_PERMISSIONS_OK_TO_ADD_NOTES;
  if (document->doc->okToFillForm ())
    flag |= POPPLER_PERMISSIONS_OK_TO_FILL_FORM;
  if (document->doc->okToAccessibility())
    flag |= POPPLER_PERMISSIONS_OK_TO_EXTRACT_CONTENTS;
  if (document->doc->okToAssemble())
    flag |= POPPLER_PERMISSIONS_OK_TO_ASSEMBLE;
  if (document->doc->okToPrintHighRes())
    flag |= POPPLER_PERMISSIONS_OK_TO_PRINT_HIGH_RESOLUTION;

  return (PopplerPermissions)flag;
}

Project: poppler

convert_page_mode (Catalog::PageMode pageMode)
{
  switch (pageMode)
    {
    case Catalog::pageModeOutlines:
      return POPPLER_PAGE_MODE_USE_OUTLINES;
    case Catalog::pageModeThumbs:
      return POPPLER_PAGE_MODE_USE_THUMBS;
    case Catalog::pageModeFullScreen:
      return POPPLER_PAGE_MODE_FULL_SCREEN;
    case Catalog::pageModeOC:
      return POPPLER_PAGE_MODE_USE_OC;
    case Catalog::pageModeAttach:
      return POPPLER_PAGE_MODE_USE_ATTACHMENTS;
    case Catalog::pageModeNone:
    default:
      return POPPLER_PAGE_MODE_UNSET;
    }
}

Project: poppler

poppler_fonts_iter_get_substitute_name (PopplerFontsIter *iter)
{
	GooString *name;
	FontInfo *info;

	info = (FontInfo *)iter->items->get (iter->index);

	name = info->getSubstituteName();
	if (name != nullptr) {
		return name->getCString();
	} else {
		return nullptr;
	}
}

Project: poppler

poppler_attachment_finalize (GObject *obj)
{
  PopplerAttachment *attachment;

  attachment = (PopplerAttachment *) obj;

  if (attachment->name)
    g_free (attachment->name);
  attachment->name = nullptr;

  if (attachment->description)
    g_free (attachment->description);
  attachment->description = nullptr;
  
  if (attachment->checksum)
    g_string_free (attachment->checksum, TRUE);
  attachment->checksum = nullptr;
  
  G_OBJECT_CLASS (poppler_attachment_parent_class)->finalize (obj);
}

Project: poppler

poppler_document_find_dest (PopplerDocument *document,
			    const gchar     *link_name)
{
	PopplerDest *dest = nullptr;
	LinkDest *link_dest = nullptr;
	GooString *g_link_name;

	g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
	g_return_val_if_fail (link_name != nullptr, NULL);

	g_link_name = new GooString (link_name);

	if (g_link_name) {
		link_dest = document->doc->findDest (g_link_name);
		delete g_link_name;
	}

	if (link_dest) {
		dest = _poppler_dest_new_goto (document, link_dest);
		delete link_dest;
	}

	return dest;
}

Project: poppler

convert_page_layout (Catalog::PageLayout pageLayout)
{
  switch (pageLayout)
    {
    case Catalog::pageLayoutSinglePage:
      return POPPLER_PAGE_LAYOUT_SINGLE_PAGE;
    case Catalog::pageLayoutOneColumn:
      return POPPLER_PAGE_LAYOUT_ONE_COLUMN;
    case Catalog::pageLayoutTwoColumnLeft:
      return POPPLER_PAGE_LAYOUT_TWO_COLUMN_LEFT;
    case Catalog::pageLayoutTwoColumnRight:
      return POPPLER_PAGE_LAYOUT_TWO_COLUMN_RIGHT;
    case Catalog::pageLayoutTwoPageLeft:
      return POPPLER_PAGE_LAYOUT_TWO_PAGE_LEFT;
    case Catalog::pageLayoutTwoPageRight:
      return POPPLER_PAGE_LAYOUT_TWO_PAGE_RIGHT;
    case Catalog::pageLayoutNone:
    default:
      return POPPLER_PAGE_LAYOUT_UNSET;
    }
}

Project: poppler

poppler_document_set_subject (PopplerDocument *document, const gchar *subject)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_subject;
  if (!subject) {
    goo_subject = nullptr;
  } else {
    goo_subject = _poppler_goo_string_from_utf8(subject);
    if (!goo_subject)
      return;
  }
  document->doc->setDocInfoSubject(goo_subject);
}

Project: poppler

poppler_layers_iter_free (PopplerLayersIter *iter)
{
  if (G_UNLIKELY (iter == nullptr))
    return;

  g_object_unref (iter->document);
  g_slice_free (PopplerLayersIter, iter);
}

Project: poppler

poppler_font_info_finalize (GObject *object)
{
        PopplerFontInfo *font_info = POPPLER_FONT_INFO (object);

        delete font_info->scanner;
        g_object_unref (font_info->document);

        G_OBJECT_CLASS (poppler_font_info_parent_class)->finalize (object);
}

Project: poppler

poppler_document_set_keywords (PopplerDocument *document, const gchar *keywords)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_keywords;
  if (!keywords) {
    goo_keywords = nullptr;
  } else {
    goo_keywords = _poppler_goo_string_from_utf8(keywords);
    if (!goo_keywords)
      return;
  }
  document->doc->setDocInfoKeywords(goo_keywords);
}

Project: poppler

_poppler_document_get_layer_rbgroup (PopplerDocument *document,
				    Layer           *layer)
{
  GList *l;

  for (l = document->layers_rbgroups; l && l->data; l = g_list_next (l)) {
    GList *group = (GList *)l->data;

    if (g_list_find (group, layer->oc))
      return group;
  }

  return nullptr;
}

Project: poppler

unicode_to_char (const Unicode *unicode,
		 int      len)
{
	static UnicodeMap *uMap = nullptr;
	if (uMap == nullptr) {
		GooString *enc = new GooString("UTF-8");
		uMap = globalParams->getUnicodeMap(enc);
		uMap->incRefCnt ();
		delete enc;
	}
		
	GooString gstr;
	gchar buf[8]; /* 8 is enough for mapping an unicode char to a string */
	int i, n;

	for (i = 0; i < len; ++i) {
		n = uMap->mapUnicode(unicode[i], buf, sizeof(buf));
		gstr.append(buf, n);
	}

	return g_strdup (gstr.getCString ());
}

Project: poppler

layer_free (Layer *layer)
{
  if (G_UNLIKELY (!layer))
    return;

  if (layer->kids) {
	  g_list_foreach (layer->kids, (GFunc)layer_free, nullptr);
	  g_list_free (layer->kids);
  }

  if (layer->label) {
	  g_free (layer->label);
  }

  g_slice_free (Layer, layer);
}

Project: poppler

poppler_document_get_page_mode (PopplerDocument *document)
{
  Catalog *catalog;

  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), POPPLER_PAGE_MODE_UNSET);

  catalog = document->doc->getCatalog ();
  if (catalog && catalog->isOk ())
    return convert_page_mode (catalog->getPageMode ());

  return POPPLER_PAGE_MODE_UNSET;
}

Project: poppler

poppler_ps_file_set_duplex (PopplerPSFile *ps_file, gboolean duplex)
{
        g_return_if_fail (ps_file->out == nullptr);

        ps_file->duplex = duplex;
}

Project: poppler

poppler_layers_iter_new (PopplerDocument *document)
{
  PopplerLayersIter *iter;
  GList *items;

  items = _poppler_document_get_layers (document);

  if (!items)
    return nullptr;

  iter = g_slice_new0 (PopplerLayersIter);
  iter->document = (PopplerDocument *)g_object_ref (document);
  iter->items = items;

  return iter;
}

Project: poppler

poppler_fonts_iter_next (PopplerFontsIter *iter)
{
	g_return_val_if_fail (iter != nullptr, FALSE);

	iter->index++;
	if (iter->index >= iter->items->getLength())
		return FALSE;

	return TRUE;
}

Project: poppler

poppler_document_new_from_data (char        *data,
                                int          length,
                                const char  *password,
                                GError     **error)
{
  PDFDoc *newDoc;
  MemStream *str;
  GooString *password_g;

  if (!globalParams) {
    globalParams = new GlobalParams();
  }
  
  // create stream
  str = new MemStream(data, 0, length, Object(objNull));

  password_g = poppler_password_to_latin1(password);
  newDoc = new PDFDoc(str, password_g, password_g);
  delete password_g;

  return _poppler_document_new_from_pdfdoc (newDoc, error);
}

Project: poppler

poppler_document_new_from_gfile (GFile        *file,
                                 const char   *password,
                                 GCancellable *cancellable,
                                 GError      **error)
{
  PopplerDocument *document;
  GFileInputStream *stream;

  g_return_val_if_fail(G_IS_FILE(file), NULL);

  if (g_file_is_native(file)) {
    gchar *uri;

    uri = g_file_get_uri(file);
    document = poppler_document_new_from_file(uri, password, error);
    g_free(uri);

    return document;
  }

  stream = g_file_read(file, cancellable, error);
  if (!stream)
    return nullptr;

  document = poppler_document_new_from_stream(G_INPUT_STREAM(stream), -1, password, cancellable, error);
  g_object_unref(stream);

  return document;
}

Project: poppler

get_optional_content_rbgroups (OCGs *ocg)
{
  Array *rb;
  GList *groups = nullptr;
  
  rb = ocg->getRBGroupsArray ();
  
  if (rb) {
    int i, j;

    for (i = 0; i < rb->getLength (); ++i) {
      Array *rb_array;
      GList *group = nullptr;

      Object obj = rb->get (i);
      if (!obj.isArray ()) {
	continue;
      }

      rb_array = obj.getArray ();
      for (j = 0; j < rb_array->getLength (); ++j) {
	OptionalContentGroup *oc;

        Object ref = rb_array->getNF (j);
	if (!ref.isRef ()) {
	  continue;
	}

	oc = ocg->findOcgByRef (ref.getRef ());
	group = g_list_prepend (group, oc);
      }

      groups = g_list_prepend (groups, group);
    }
  }

  return groups;
}

Project: poppler

poppler_document_has_attachments (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), FALSE);

  return (poppler_document_get_n_attachments (document) != 0);
}

Project: poppler

poppler_fonts_iter_free (PopplerFontsIter *iter)
{
	if (G_UNLIKELY (iter == nullptr))
		return;

	deleteGooList<FontInfo> (iter->items);

	g_slice_free (PopplerFontsIter, iter);
}

Project: poppler

poppler_document_set_creation_date (PopplerDocument *document,
                                    time_t creation_date)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *str = creation_date == (time_t)-1 ? nullptr : timeToDateString (&creation_date);
  document->doc->setDocInfoCreatDate (str);
}

Project: poppler

poppler_attachment_class_init (PopplerAttachmentClass *klass)
{
  G_OBJECT_CLASS (klass)->dispose = poppler_attachment_dispose;
  G_OBJECT_CLASS (klass)->finalize = poppler_attachment_finalize;
  g_type_class_add_private (klass, sizeof (PopplerAttachmentPrivate));
}

Project: poppler

handle_save_error (int      err_code,
		   GError **error)
{
  switch (err_code)
    {
    case errNone:
      break;
    case errOpenFile:
      g_set_error (error, POPPLER_ERROR,
		   POPPLER_ERROR_OPEN_FILE,
		   "Failed to open file for writing");
      break;
    case errEncrypted:
      g_set_error (error, POPPLER_ERROR,
		   POPPLER_ERROR_ENCRYPTED,
		   "Document is encrypted");
      break;
    default:
      g_set_error (error, POPPLER_ERROR,
		   POPPLER_ERROR_INVALID,
		   "Failed to save document");
    }

  return err_code == errNone;
}

Project: poppler

poppler_ps_file_init (PopplerPSFile *ps_file)
{
        ps_file->out = nullptr;
        ps_file->paper_width = -1;
        ps_file->paper_height = -1;
        ps_file->duplex = FALSE;
}

Project: poppler

save_helper (const gchar  *buf,
	     gsize         count,
	     gpointer      data,
	     GError      **error)
{
  FILE *f = (FILE *) data;
  gsize n;

  n = fwrite (buf, 1, count, f);
  if (n != count)
    {
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   _("Error writing to image file: %s"),
		   g_strerror (errno));
      return FALSE;
    }

  return TRUE;
}

Project: poppler

poppler_font_info_free (PopplerFontInfo *font_info)
{
	g_return_if_fail (font_info != nullptr);

	g_object_unref (font_info);
}

Project: poppler

poppler_layers_iter_get_title (PopplerLayersIter *iter)
{
  Layer *layer;
  
  g_return_val_if_fail (iter != nullptr, NULL);
  
  layer = (Layer *)g_list_nth_data (iter->items, iter->index);

  return layer->label ? g_strdup (layer->label) : nullptr;
}

Project: poppler

_poppler_document_get_layers (PopplerDocument *document)
{
  if (!document->layers) {
    Catalog *catalog = document->doc->getCatalog ();
    OCGs *ocg = catalog->getOptContentConfig ();

    if (!ocg)
      return nullptr;
    
    document->layers = get_optional_content_items (ocg);
    document->layers_rbgroups = get_optional_content_rbgroups (ocg);
  }

  return document->layers;
}

Project: poppler

poppler_document_set_author (PopplerDocument *document, const gchar *author)
{
  g_return_if_fail (POPPLER_IS_DOCUMENT (document));

  GooString *goo_author;
  if (!author) {
    goo_author = nullptr;
  } else {
    goo_author = _poppler_goo_string_from_utf8(author);
    if (!goo_author)
      return;
  }
  document->doc->setDocInfoAuthor(goo_author);
}

Project: poppler

_poppler_attachment_new (FileSpec *emb_file)
{
  PopplerAttachment *attachment;
  PopplerAttachmentPrivate *priv;
  EmbFile *embFile;

  g_assert (emb_file != nullptr);

  attachment = (PopplerAttachment *) g_object_new (POPPLER_TYPE_ATTACHMENT, nullptr);
  priv = POPPLER_ATTACHMENT_GET_PRIVATE (attachment);

  if (emb_file->getFileName ())
    attachment->name = _poppler_goo_string_to_utf8 (emb_file->getFileName ());
  if (emb_file->getDescription ())
    attachment->description = _poppler_goo_string_to_utf8 (emb_file->getDescription ());

  embFile = emb_file->getEmbeddedFile();
  if (embFile != NULL && embFile->streamObject()->isStream())
    {
      attachment->size = embFile->size ();

      if (embFile->createDate ())
        _poppler_convert_pdf_date_to_gtime (embFile->createDate (), (time_t *)&attachment->ctime);
      if (embFile->modDate ())
        _poppler_convert_pdf_date_to_gtime (embFile->modDate (), (time_t *)&attachment->mtime);

      if (embFile->checksum () && embFile->checksum ()->getLength () > 0)
        attachment->checksum = g_string_new_len (embFile->checksum ()->getCString (),
                                                 embFile->checksum ()->getLength ());
      priv->obj_stream = embFile->streamObject()->copy();
    }
  else
    {
      g_warning ("Missing stream object for embedded file");
      g_clear_object (&attachment);
    }

  return attachment;
}

Project: poppler

poppler_document_get_page_by_label (PopplerDocument  *document,
				    const char       *label)
{
  Catalog *catalog;
  GooString label_g(label);
  int index;

  catalog = document->doc->getCatalog();
  if (!catalog->labelToIndex (&label_g, &index))
    return nullptr;

  return poppler_document_get_page (document, index);
}

Project: poppler

poppler_attachment_init (PopplerAttachment *attachment)
{
}

Project: poppler

layer_new (OptionalContentGroup *oc)
{
  Layer *layer;

  layer = g_slice_new0 (Layer);
  layer->oc = oc;

  return layer;
}

Project: poppler

poppler_font_info_scan (PopplerFontInfo   *font_info,
			int                n_pages,
			PopplerFontsIter **iter)
{
	GooList *items;

	g_return_val_if_fail (iter != nullptr, FALSE);

	items = font_info->scanner->scan(n_pages);

	if (items == nullptr) {
		*iter = nullptr;
	} else if (items->getLength() == 0) {
		*iter = nullptr;
		delete items;
	} else {
		*iter = poppler_fonts_iter_new(items);
	}
	
	return (items != nullptr);
}

Project: poppler

poppler_document_new_from_file (const char  *uri,
				const char  *password,
				GError     **error)
{
  PDFDoc *newDoc;
  GooString *password_g;
  char *filename;

  if (!globalParams) {
    globalParams = new GlobalParams();
  }

  filename = g_filename_from_uri (uri, nullptr, error);
  if (!filename)
    return nullptr;

  password_g = poppler_password_to_latin1(password);

#ifdef G_OS_WIN32
  wchar_t *filenameW;
  int length;

  length = MultiByteToWideChar(CP_UTF8, 0, filename, -1, nullptr, 0);

  filenameW = new WCHAR[length];
  if (!filenameW)
      return NULL;

  length = MultiByteToWideChar(CP_UTF8, 0, filename, -1, filenameW, length);

  newDoc = new PDFDoc(filenameW, length, password_g, password_g);
  delete [] filenameW;
#else
  GooString *filename_g;
  filename_g = new GooString (filename);
  newDoc = new PDFDoc(filename_g, password_g, password_g);
#endif
  g_free (filename);

  delete password_g;

  return _poppler_document_new_from_pdfdoc (newDoc, error);
}

Project: poppler

poppler_attachment_dispose (GObject *obj)
{
  PopplerAttachmentPrivate *priv;

  priv = POPPLER_ATTACHMENT_GET_PRIVATE (obj);
  priv->obj_stream = Object();

  G_OBJECT_CLASS (poppler_attachment_parent_class)->dispose (obj);
}

Project: poppler

poppler_password_to_latin1 (const gchar *password)
{
  gchar *password_latin;
  GooString *password_g;

  if (!password)
    return nullptr;

  password_latin = g_convert(password, -1, "ISO-8859-1", "UTF-8",
                             nullptr, nullptr, nullptr);
  password_g = new GooString (password_latin);
  g_free (password_latin);

  return password_g;
}

Project: poppler

poppler_document_get_producer (PopplerDocument *document)
{
  g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);

  GooString *goo_producer = document->doc->getDocInfoProducer();
  gchar *utf8 = _poppler_goo_string_to_utf8(goo_producer);
  delete goo_producer;

  return utf8;
}

Project: poppler

poppler_index_iter_copy (PopplerIndexIter *iter)
{
	PopplerIndexIter *new_iter;

	g_return_val_if_fail (iter != nullptr, NULL);

	new_iter = g_slice_dup (PopplerIndexIter, iter);
	new_iter->document = (PopplerDocument *) g_object_ref (new_iter->document);

	return new_iter;
}

Project: poppler

poppler_layers_iter_next (PopplerLayersIter *iter)
{
  g_return_val_if_fail (iter != nullptr, FALSE);

  iter->index++;
  if (iter->index >= (gint)g_list_length (iter->items))
    return FALSE;
  
  return TRUE;
}

Project: poppler

poppler_document_init (PopplerDocument *document)
{
}

Project: poppler

poppler_font_info_class_init (PopplerFontInfoClass *klass)
{
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

        gobject_class->finalize = poppler_font_info_finalize;
}

Project: poppler

poppler_document_get_form_field (PopplerDocument *document,
				 gint             id)
{
  Page *page;
  unsigned pageNum;
  unsigned fieldNum;
  FormPageWidgets *widgets;
  FormWidget *field;

  FormWidget::decodeID (id, &pageNum, &fieldNum);

  page = document->doc->getPage (pageNum);
  if (!page)
    return nullptr;

  widgets = page->getFormWidgets ();
  if (!widgets)
    return nullptr;

  field = widgets->getWidget (fieldNum);
  if (field)
    return _poppler_form_field_new (document, field);

  return nullptr;
}