add packaging
[platform/upstream/nettle.git] / sexp-transport.c
1 /* sexp-transport.c
2  *
3  * Parsing s-expressions in transport format.
4  */
5
6 /* nettle, low-level cryptographics library
7  *
8  * Copyright (C) 2002 Niels Möller
9  *  
10  * The nettle library is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or (at your
13  * option) any later version.
14  * 
15  * The nettle library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18  * License for more details.
19  * 
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with the nettle library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23  * MA 02111-1301, USA.
24  */
25
26 #if HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <assert.h>
31 #include <string.h>
32
33 #include "sexp.h"
34
35 #include "base64.h"
36
37 /* NOTE: Decodes the input string in place */
38 int
39 sexp_transport_iterator_first(struct sexp_iterator *iterator,
40                               unsigned length, uint8_t *input)
41 {
42   /* We first base64 decode any transport encoded sexp at the start of
43    * the input. */
44
45   unsigned in = 0;
46   unsigned out = 0;
47
48   while (in < length)
49     switch(input[in])
50       {
51       case ' ':  /* SPC, TAB, LF, CR */
52       case '\t':
53       case '\n':
54       case '\r':
55         in++;
56         break;
57           
58       case ';':  /* Comments */
59         while (++in < length && input[in] != '\n')
60           ;
61         break;
62           
63       case '{':
64         {
65           /* Found transport encoding */
66           struct base64_decode_ctx ctx;
67           unsigned coded_length;
68           unsigned end;
69
70           for (end = ++in; end < length && input[end] != '}'; end++)
71             ;
72
73           if (end == length)
74             return 0;
75             
76           base64_decode_init(&ctx);
77           coded_length = end - in;
78           
79           if (base64_decode_update(&ctx, &coded_length, input + out,
80                                    coded_length, input + in)
81               && base64_decode_final(&ctx))
82             {     
83               out += coded_length;
84               in = end + 1;
85             }
86           else
87             return 0;
88           
89           break;
90         }
91       default:
92         /* Expression isn't in transport encoding. Rest of the input
93          * should be in canonical encoding. */
94         goto transport_done;
95       }
96   
97  transport_done:
98
99   /* Here, we have two, possibly empty, input parts in canonical
100    * encoding:
101    *
102    * 0...out-1,  in...length -1
103    *
104    * If the input was already in canonical encoding, out = 0 and in =
105    * amount of leading space.
106    *
107    * If all input was in transport encoding, in == length.
108    */
109   if (!out)
110     {
111       input += in;
112       length -= in;
113     }
114   else if (in == length)
115     length = out;
116   else if (out == in)
117     /* Unusual case, nothing happens */
118     ;
119   else
120     {
121       /* Both parts non-empty */
122       assert(out < in);
123       memmove(input + out, input + in, length - in);
124       length -= (in - out);
125     }
126
127   return sexp_iterator_first(iterator, length, input);
128 }