encode_uint32 second parameter should be uint32_t, not unsigned long
[git-daemon2.git] / client / base64.c
blobf94722c6e27c6c11660cd2c7ac7eade9ff93bcf2
1 #include "base64.h"
2 #include "git-compat-util.h"
4 void encode_uint32(unsigned char *ptr, uint32_t value)
6 ptr[0] = (unsigned char)(value >> 24);
7 ptr[1] = (unsigned char)(value >> 16);
8 ptr[2] = (unsigned char)(value >> 8);
9 ptr[3] = (unsigned char)(value);
12 /* Base64 character value */
13 static int char_value(unsigned char ch)
15 if (ch >= 'A' && ch <= 'Z')
16 return ch - 'A';
17 if (ch >= 'a' && ch <= 'z')
18 return ch - 'a' + 26;
19 if (ch >= '0' && ch <= '9')
20 return ch - '0' + 52;
21 if (ch == '+')
22 return 62;
23 if (ch == '/')
24 return 63;
25 return -1;
28 /* Decode Base64 chunk. */
29 unsigned char *decode_base64_chunk(const unsigned char *chunk,
30 size_t chunk_len, size_t *key_len)
32 unsigned char *ret;
33 unsigned blockmod = 0;
34 int buf[4];
35 size_t i;
37 ret = xmalloc((chunk_len + 3) / 4 * 3);
38 *key_len = 0;
40 for(i = 0; i < chunk_len; i++) {
41 buf[blockmod] = char_value(chunk[i]);
42 if (buf[blockmod] >= 0)
43 blockmod++;
44 else
45 buf[blockmod] = 0;
46 if(blockmod == 4) {
47 int v = (buf[0] << 18) | (buf[1] << 12) |
48 (buf[2] << 6) | buf[3];
49 ret[(*key_len)++] = (unsigned char)(v >> 16);
50 ret[(*key_len)++] = (unsigned char)(v >> 8);
51 ret[(*key_len)++] = (unsigned char)(v);
52 blockmod = 0;
53 buf[0] = buf[1] = buf[2] = buf[3] = 0;
56 if(blockmod > 0) {
57 int v = (buf[0] << 18) | (buf[1] << 12) |
58 (buf[2] << 6) | buf[3];
59 if (blockmod > 1)
60 ret[(*key_len)++] = (unsigned char)(v >> 16);
61 if (blockmod > 2)
62 ret[(*key_len)++] = (unsigned char)(v >> 8);
64 return ret;
67 /* Return address of next (nonempty) line, or NULL if none. */
68 const unsigned char *next_line(const unsigned char *blob,
69 size_t *remaining)
71 while (*blob != '\r' && *blob != '\n') {
72 blob++;
73 (*remaining)--;
74 if (!*remaining)
75 return NULL;
77 while (*blob == '\r' || *blob == '\n') {
78 blob++;
79 (*remaining)--;
80 if (!*remaining)
81 return NULL;
83 return blob;
86 #define STATUS_INIT 0
87 #define STATUS_HEADER 1
88 #define STATUS_CONTINUE 2
89 #define STATUS_EOL 3
90 #define STATUS_EOL_CONTINUE 4
92 /* Find start of base64 blob. */
93 const unsigned char *base64_blob_start(const unsigned char *blob,
94 size_t *remaining)
96 int status = STATUS_INIT;
97 const unsigned char *line_start;
98 size_t size_start;
100 line_start = blob;
101 size_start = *remaining;
103 while(1) {
104 switch(status) {
105 case STATUS_INIT:
106 if (!*remaining || *blob == '\r' || *blob == '\n') {
107 /* Back off to start of line. */
108 blob = line_start;
109 *remaining = size_start;
110 return blob;
112 if (*blob == ':')
113 status = STATUS_HEADER;
114 break;
115 case STATUS_HEADER:
116 if (!*remaining) {
117 *remaining = 0;
118 return NULL;
120 if (*blob == '\r' || *blob == '\n')
121 status = STATUS_EOL;
122 if (*blob == '\\')
123 status = STATUS_CONTINUE;
124 break;
125 case STATUS_CONTINUE:
126 if (!*remaining) {
127 *remaining = 0;
128 return NULL;
130 if (*blob == '\r' || *blob == '\n')
131 status = STATUS_EOL_CONTINUE;
132 else
133 status = STATUS_HEADER;
134 break;
135 case STATUS_EOL:
136 if (!*remaining) {
137 *remaining = 0;
138 return NULL;
140 if (*blob != '\r' && *blob != '\n') {
141 /* Mark line start and back off by one. */
142 line_start = blob;
143 size_start = *remaining;
144 blob--;
145 (*remaining)++;
146 status = STATUS_INIT;
148 break;
149 case STATUS_EOL_CONTINUE:
150 if (!*remaining) {
151 *remaining = 0;
152 return NULL;
154 if (*blob != '\r' && *blob != '\n') {
155 /* Mark line start and back off by one. */
156 line_start = blob;
157 size_start = *remaining;
158 blob--;
159 (*remaining)++;
160 status = STATUS_HEADER;
162 break;
164 blob++;
165 (*remaining)--;