Fix more spelling
[gnupg.git] / common / b64dec.c
index af223ae..c84c35a 100644 (file)
@@ -1,19 +1,20 @@
 /* b64dec.c - Simple Base64 decoder.
- * Copyright (C) 2008 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011, 2016 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * This file 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.
  *
- * GnuPG is distributed in the hope that it will be useful,
+ * This file 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 General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
+ * 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/>.
  */
 
@@ -29,7 +30,7 @@
 
 
 /* The reverse base-64 list used for base-64 decoding. */
-static unsigned char const asctobin[128] = 
+static unsigned char const asctobin[128] =
   {
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@@ -49,9 +50,9 @@ static unsigned char const asctobin[128] =
     0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
   };
 
-enum decoder_states 
+enum decoder_states
   {
-    s_init, s_idle, s_lfseen, s_begin,
+    s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
     s_b64_0, s_b64_1, s_b64_2, s_b64_3,
     s_waitendtitle, s_waitend
   };
@@ -61,27 +62,22 @@ enum decoder_states
 /* Initialize the context for the base64 decoder.  If TITLE is NULL a
    plain base64 decoding is done.  If it is the empty string the
    decoder will skip everything until a "-----BEGIN " line has been
-   seen, decoding ends at a "----END " line.
-   
-   Not yet implemented: If TITLE is either "PGP" or begins with "PGP "
-   the PGP armor lines are skipped as well.  */
+   seen, decoding ends at a "----END " line.  */
 gpg_error_t
 b64dec_start (struct b64state *state, const char *title)
 {
   memset (state, 0, sizeof *state);
   if (title)
     {
-      if (!strncmp (title, "PGP", 3) && (!title[3] || title[3] == ' '))
-        return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
-
       state->title = xtrystrdup (title);
       if (!state->title)
-        return gpg_error_from_syserror ();
-      state->idx = s_init;
+        state->lasterr = gpg_error_from_syserror ();
+      else
+        state->idx = s_init;
     }
   else
     state->idx = s_b64_0;
-  return 0;
+  return state->lasterr;
 }
 
 
@@ -93,17 +89,24 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
 {
   enum decoder_states ds = state->idx;
   unsigned char val = state->radbuf[0];
-  int pos = state->quad_count; 
+  int pos = state->quad_count;
   char *d, *s;
 
+  if (state->lasterr)
+    return state->lasterr;
+
   if (state->stop_seen)
     {
       *r_nbytes = 0;
-      return gpg_error (GPG_ERR_EOF);
+      state->lasterr = gpg_error (GPG_ERR_EOF);
+      xfree (state->title);
+      state->title = NULL;
+      return state->lasterr;
     }
 
   for (s=d=buffer; length && !state->stop_seen; length--, s++)
     {
+    again:
       switch (ds)
         {
         case s_idle:
@@ -117,12 +120,42 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
           ds = s_lfseen;
         case s_lfseen:
           if (*s != "-----BEGIN "[pos])
-            ds = s_idle;
+            {
+              ds = s_idle;
+              goto again;
+            }
           else if (pos == 10)
-            ds = s_begin;
+            {
+              pos = 0;
+              ds = s_beginseen;
+            }
+          else
+            pos++;
+          break;
+        case s_beginseen:
+          if (*s != "PGP "[pos])
+            ds = s_begin; /* Not a PGP armor.  */
+          else if (pos == 3)
+            ds = s_waitheader;
           else
             pos++;
           break;
+        case s_waitheader:
+          if (*s == '\n')
+            ds = s_waitblank;
+          break;
+        case s_waitblank:
+          if (*s == '\n')
+            ds = s_b64_0; /* blank line found.  */
+          else if (*s == ' ' || *s == '\r' || *s == '\t')
+            ; /* Ignore spaces. */
+          else
+            {
+              /* Armor header line.  Note that we don't care that our
+               * FSM accepts a header prefixed with spaces.  */
+              ds = s_waitheader; /* Wait for next header.  */
+            }
+          break;
         case s_begin:
           if (*s == '\n')
             ds = s_b64_0;
@@ -134,7 +167,7 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
           {
             int c;
 
-            if (*s == '-' && state->title) 
+            if (*s == '-' && state->title)
               {
                 /* Not a valid Base64 character: assume end
                    header.  */
@@ -149,7 +182,7 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
               }
             else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
               ; /* Skip white spaces. */
-            else if ( (*s & 0x80) 
+            else if ( (*s & 0x80)
                       || (c = asctobin[*(unsigned char *)s]) == 255)
               {
                 /* Skip invalid encodings.  */
@@ -189,8 +222,8 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
         case s_waitend:
           if ( *s == '\n')
             state->stop_seen = 1;
-          break; 
-        default: 
+          break;
+        default:
           BUG();
         }
     }
@@ -198,7 +231,7 @@ b64dec_proc (struct b64state *state, void *buffer, size_t length,
 
   state->idx = ds;
   state->radbuf[0] = val;
-  state->quad_count = pos; 
+  state->quad_count = pos;
   *r_nbytes = (d -(char*) buffer);
   return 0;
 }
@@ -212,6 +245,9 @@ b64dec_finish (struct b64state *state)
 {
   xfree (state->title);
   state->title = NULL;
+
+  if (state->lasterr)
+    return state->lasterr;
+
   return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
 }
-