]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
(sexp_transport_iterator_first): New file and
authorNiels Möller <nisse@lysator.liu.se>
Mon, 21 Oct 2002 13:40:37 +0000 (15:40 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 21 Oct 2002 13:40:37 +0000 (15:40 +0200)
function.

Rev: src/nettle/sexp-transport.c:1.1

sexp-transport.c [new file with mode: 0644]

diff --git a/sexp-transport.c b/sexp-transport.c
new file mode 100644 (file)
index 0000000..7737891
--- /dev/null
@@ -0,0 +1,118 @@
+/* sexp-transport.c
+ *
+ * Parsing s-expressions in transport format.
+ */
+
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2002 Niels Möller
+ *  
+ * The nettle 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.
+ * 
+ * The nettle 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 the nettle library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#include "sexp.h"
+
+#include "base64.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* NOTE: Decodes the input string in place */
+int
+sexp_transport_iterator_first(struct sexp_iterator *iterator,
+                             unsigned length, uint8_t *input)
+{
+  /* We first base64 decode any transport encoded sexp at the start of
+   * the input. */
+
+  unsigned in = 0;
+  unsigned out = 0;
+
+  while (in < length)
+    switch(input[in])
+      {
+      case ' ':  /* SPC, TAB, LF, CR */
+      case '\t':
+      case '\n':
+      case '\r':
+       in++;
+       break;
+         
+      case ';':  /* Comments */
+       while (++in < length && input[in] != '\n')
+         ;
+       break;
+         
+      case '{':
+       {
+         /* Found transport encoding */
+         struct base64_decode_ctx ctx;
+         unsigned end;
+
+         for (end = ++in; end < length && input[end] != '}'; end++)
+           ;
+
+         if (end == length)
+           return 0;
+           
+         base64_decode_init(&ctx);
+           
+         out += base64_decode_update(&ctx, input + out,
+                                     end - in, input + in);
+         if (!base64_decode_status(&ctx))
+           return 0;
+         in = end + 1;
+
+         break;
+       }
+      default:
+       /* Expression isn't in transport encoding. Rest of the input
+        * should be in canonical encoding. */
+       goto transport_done;
+      }
+  
+ transport_done:
+
+  /* Here, we have two, possibly empty, input parts in canonical
+   * encoding:
+   *
+   * 0...out-1,  in...length -1
+   *
+   * If the input was already in canonical encoding, out = 0 and in =
+   * amount of leading space.
+   *
+   * If all input was in transport encoding, in == length.
+   */
+  if (!out)
+    {
+      input += in;
+      length -= in;
+    }
+  else if (in == length)
+    length = out;
+  else if (out == in)
+    /* Unusual case, nothing happens */
+    ;
+  else
+    {
+      /* Both parts non-empty */
+      assert(out < in);
+      memmove(input + out, input + in, length - in);
+      length -= (in - out);
+    }
+
+  return sexp_iterator_first(iterator, length, input);
+}