/* Copyright © 2013 Canonical Limited
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Ryan Lortie <desrt@desrt.ca>
 */

#include "config.h"

#include "thumbnail-verify.h"

#include <string.h>

/* Begin code to check the validity of thumbnail files.  In order to do
 * that we need to parse enough PNG in order to get the Thumb::URI,
 * Thumb::MTime and Thumb::Size tags out of the file.  Fortunately this
 * is relatively easy.
 */
typedef struct
{
  const gchar *uri;
  guint64      mtime;
  guint64      size;
} ExpectedInfo;

/* We *require* matches on URI and MTime, but the Size field is optional
 * (as per the spec).
 *
 * http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html
 */
#define MATCHED_URI    (1u << 0)
#define MATCHED_MTIME  (1u << 1)
#define MATCHED_ALL    (MATCHED_URI | MATCHED_MTIME)

static gboolean
check_integer_match (guint64      expected,
                     const gchar *value,
                     guint32      value_size)
{
  /* Would be nice to g_ascii_strtoll here, but we don't have a variant
   * that works on strings that are not nul-terminated.
   *
   * It's easy enough to do it ourselves...
   */
  if (expected == 0)  /* special case: "0" */
    return value_size == 1 && value[0] == '0';

  /* Check each digit, as long as we have data from both */
  while (expected && value_size)
    {
      /* Check the low-order digit */
      if (value[value_size - 1] != (gchar) ((expected % 10) + '0'))
        return FALSE;

      /* Move on... */
      expected /= 10;
      value_size--;
    }

  /* Make sure nothing is left over, on either side */
  return !expected && !value_size;
}

static gboolean
check_png_info_chunk (ExpectedInfo *expected_info,
                      const gchar  *key,
                      guint32       key_size,
                      const gchar  *value,
                      guint32       value_size,
                      guint        *required_matches)
{
  if (key_size == 10 && memcmp (key, "Thumb::URI", 10) == 0)
    {
      gsize expected_size;

      expected_size = strlen (expected_info->uri);

      if (expected_size != value_size)
        return FALSE;

      if (memcmp (expected_info->uri, value, value_size) != 0)
        return FALSE;

      *required_matches |= MATCHED_URI;
    }

  else if (key_size == 12 && memcmp (key, "Thumb::MTime", 12) == 0)
    {
      if (!check_integer_match (expected_info->mtime, value, value_size))
        return FALSE;

      *required_matches |= MATCHED_MTIME;
    }

  else if (key_size == 11 && memcmp (key, "Thumb::Size", 11) == 0)
    {
      /* A match on Thumb::Size is not required for success, but if we
       * find this optional field and it's wrong, we should reject the
       * thumbnail.
       */
      if (!check_integer_match (expected_info->size, value, value_size))
        return FALSE;
    }

  return TRUE;
}

static gboolean
check_thumbnail_validity (ExpectedInfo *expected_info,
                          const gchar  *contents,
                          gsize         size)
{
  guint required_matches = 0;

  /* Reference: http://www.w3.org/TR/PNG/ */
  if (size < 8)
    return FALSE;

  if (memcmp (contents, "\x89PNG\r\n\x1a\n", 8) != 0)
    return FALSE;

  contents += 8, size -= 8;

  /* We need at least 12 bytes to have a chunk... */
  while (size >= 12)
    {
      guint32 chunk_size_be;
      guint32 chunk_size;

      /* PNG is not an aligned file format so we have to be careful
       * about reading integers...
       */
      memcpy (&chunk_size_be, contents, 4);
      chunk_size = GUINT32_FROM_BE (chunk_size_be);

      contents += 4, size -= 4;

      /* After consuming the size field, we need to have enough bytes
       * for 4 bytes type field, chunk_size bytes for data, then 4 byte
       * for CRC (which we ignore)
       *
       * We just read chunk_size from the file, so it may be very large.
       * Make sure it won't wrap when we add 8 to it.
       */
      if (G_MAXUINT32 - chunk_size < 8 || size < chunk_size + 8)
        goto out;

      /* We are only interested in tEXt fields */
      if (memcmp (contents, "tEXt", 4) == 0)
        {
          const gchar *key = contents + 4;
          guint32 key_size;

          /* We need to find the nul separator character that splits the
           * key/value.  The value is not terminated.
           *
           * If we find no nul then we just ignore the field.
           *
           * value may contain extra nuls, but check_png_info_chunk()
           * can handle that.
           */
          for (key_size = 0; key_size < chunk_size; key_size++)
            {
              if (key[key_size] == '\0')
                {
                  const gchar *value;
                  guint32 value_size;

                  /* Since key_size < chunk_size, value_size is
                   * definitely non-negative.
                   */
                  value_size = chunk_size - key_size - 1;
                  value = key + key_size + 1;

                  /* We found the separator character. */
                  if (!check_png_info_chunk (expected_info,
                                             key, key_size,
                                             value, value_size,
                                             &required_matches))
                    return FALSE;
                }
            }
        }
      else
        {
          /* A bit of a hack: assume that all tEXt chunks will appear
           * together.  Therefore, if we have already seen both required
           * fields and then see a non-tEXt chunk then we can assume we
           * are done.
           *
           * The common case is that the tEXt chunks come at the start
           * of the file before any of the image data.  This trick means
           * that we will only fault in a single page (4k) whereas many
           * thumbnails (particularly the large ones) can approach 100k
           * in size.
           */
          if (required_matches == MATCHED_ALL)
            goto out;
        }

      /* skip to the next chunk, ignoring CRC. */
      contents += 4, size -= 4;                         /* type field */
      contents += chunk_size, size -= chunk_size;       /* data */
      contents += 4, size -= 4;                         /* CRC */
    }

out:
  return required_matches == MATCHED_ALL;
}

gboolean
thumbnail_verify (const char     *thumbnail_path,
                  const gchar    *file_uri,
                  const GLocalFileStat *file_stat_buf)
{
  gboolean thumbnail_is_valid = FALSE;
  ExpectedInfo expected_info;
  GMappedFile *file;

  if (file_stat_buf == NULL)
    return FALSE;

  expected_info.uri = file_uri;
#ifdef G_OS_WIN32
  expected_info.mtime = (guint64) file_stat_buf->st_mtim.tv_sec;
#else
  expected_info.mtime = _g_stat_mtime (file_stat_buf);
#endif
  expected_info.size = _g_stat_size (file_stat_buf);

  file = g_mapped_file_new (thumbnail_path, FALSE, NULL);
  if (file)
    {
      thumbnail_is_valid = check_thumbnail_validity (&expected_info,
                                                     g_mapped_file_get_contents (file),
                                                     g_mapped_file_get_length (file));
      g_mapped_file_unref (file);
    }

  return thumbnail_is_valid;
}
