json: Add additional commands to help
[gpgme.git] / src / data-identify.c
index ae31117..857d06c 100644 (file)
@@ -14,7 +14,7 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with this program; if not, see <http://www.gnu.org/licenses/>.
+   License along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #if HAVE_CONFIG_H
@@ -95,6 +95,11 @@ next_openpgp_packet (unsigned char const **bufptr, size_t *buflen,
   if (!len)
     return gpg_error (GPG_ERR_NO_DATA);
 
+  /* First some blacklisting.  */
+  if (len >= 4 && !memcmp (buf, "\x89PNG", 4))
+    return gpg_error (GPG_ERR_INV_PACKET); /* This is a PNG file.  */
+
+  /* Start parsing.  */
   ctb = *buf++; len--;
   if ( !(ctb & 0x80) )
     return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */
@@ -271,12 +276,36 @@ pgp_binary_detection (const void *image_arg, size_t imagelen)
 }
 
 
+/* This is probably an armored "PGP MESSAGE" which can encode
+ * different PGP data types.  STRING is modified after a call to this
+ * function. */
+static gpgme_data_type_t
+inspect_pgp_message (char *string)
+{
+  struct b64state state;
+  size_t nbytes;
+
+  if (_gpgme_b64dec_start (&state, ""))
+    return GPGME_DATA_TYPE_INVALID; /* oops */
+
+  if (_gpgme_b64dec_proc (&state, string, strlen (string), &nbytes))
+    {
+      _gpgme_b64dec_finish (&state);
+      return GPGME_DATA_TYPE_UNKNOWN; /* bad encoding etc. */
+    }
+  _gpgme_b64dec_finish (&state);
+  string[nbytes] = 0; /* Better append a Nul. */
+
+  return pgp_binary_detection (string, nbytes);
+}
+
+
 /* Note that DATA may be binary but a final nul is required so that
    string operations will find a terminator.
 
    Returns: GPGME_DATA_TYPE_xxxx */
 static gpgme_data_type_t
-basic_detection (const char *data, size_t datalen)
+basic_detection (char *data, size_t datalen)
 {
   tlvinfo_t ti;
   const char *s;
@@ -419,7 +448,7 @@ basic_detection (const char *data, size_t datalen)
           if (!strncmp (s+11, "PGP ", 4))
             {
               if (!strncmp (s+15, "SIGNATURE", 9))
-                return GPGME_DATA_TYPE_PGP_SIGNED;
+                return GPGME_DATA_TYPE_PGP_SIGNATURE;
               if (!strncmp (s+15, "SIGNED MESSAGE", 14))
                 return GPGME_DATA_TYPE_PGP_SIGNED;
               if (!strncmp (s+15, "PUBLIC KEY BLOCK", 16))
@@ -430,7 +459,8 @@ basic_detection (const char *data, size_t datalen)
                 return GPGME_DATA_TYPE_PGP_KEY;
               if (!strncmp (s+15, "ARMORED FILE", 12))
                 return GPGME_DATA_TYPE_UNKNOWN;
-              return GPGME_DATA_TYPE_PGP_OTHER; /* PGP MESSAGE */
+
+              return inspect_pgp_message (data);
             }
           if (!strncmp (s+11, "CERTIFICATE", 11))
             return GPGME_DATA_TYPE_X509_CERT;
@@ -459,6 +489,8 @@ gpgme_data_identify (gpgme_data_t dh, int reserved)
   int n;
   gpgme_off_t off;
 
+  (void)reserved;
+
   /* Check whether we can seek the data object.  */
   off = gpgme_data_seek (dh, 0, SEEK_CUR);
   if (off == (gpgme_off_t)(-1))