/addons/Oauth/source/Oauth/_aux.c

https://github.com/basuke/io · C · 334 lines · 255 code · 67 blank · 12 comment · 82 complexity · 173a85c94548107dbde52ec16150d1c3 MD5 · raw file

  1. /*
  2. * aux.c
  3. *
  4. * Auxilliary facilities
  5. */
  6. /*
  7. "aux" is a reserved device name on Windows and causes both git-bash and CMake to error out when accessing the file name.
  8. I've changed the file names to _aux.h and _aux.c to fix it. My apologies to the original author of OAuth. --Dennis Ferron
  9. */
  10. #include "_aux.h"
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <stdarg.h>
  14. #include <assert.h>
  15. void string_init(struct string *self)
  16. {
  17. self->size = 0;
  18. self->len = 0;
  19. self->data = NULL;
  20. }
  21. void string_adjustlen(struct string *self, const int factor)
  22. {
  23. self->len-=factor;
  24. self->data[self->len] = '\0';
  25. }
  26. char *string_cString(struct string *self)
  27. {
  28. char *cString = calloc(self->len + 1, 1);
  29. memcpy(cString, self->data, self->len);
  30. return cString;
  31. }
  32. void string_append_urlencoded_rfc3986(struct string *self, const char *p, const size_t len)
  33. {
  34. const uint8_t *data = (uint8_t *)p, *cp = data;
  35. const uint8_t *end = data + len;
  36. char _t[3];
  37. while (data != end)
  38. {
  39. if ((*data >='a' && *data <='z') || (*data >='A' && *data <='Z') || (*data >='0' && *data <='9') || *data == '-' || *data == '.' || *data == '_' || *data == '~')
  40. ++data;
  41. else
  42. {
  43. string_append(self, cp, data - cp);
  44. _t[0] = '%';
  45. _t[1] = ToHex(*data >> 4);
  46. _t[2] = ToHex(*data & 15);
  47. string_append(self, _t, 3);
  48. cp = ++data;
  49. }
  50. }
  51. string_append(self, cp, data - cp);
  52. }
  53. void string_reset(struct string *self)
  54. {
  55. self->len = 0;
  56. if (self->data)
  57. self->data[0] = '\0';
  58. }
  59. void string_dealloc(struct string *self)
  60. {
  61. if (self->data)
  62. free(self->data);
  63. }
  64. size_t string_capacity(struct string *self)
  65. {
  66. return self->size - self->len;
  67. }
  68. void string_set_capacity(struct string *self, const size_t n)
  69. {
  70. const size_t c = string_capacity(self);
  71. if (c < n)
  72. {
  73. self->size+=(n - c) + 2;
  74. self->data = (char *)realloc(self->data, self->size * sizeof(char));
  75. }
  76. }
  77. void string_append(struct string *self, const void *p, const size_t l)
  78. {
  79. string_set_capacity(self, l);
  80. memcpy(self->data + self->len, p, l);
  81. self->len+=l;
  82. self->data[self->len] = '\0';
  83. }
  84. void string_appendfmt(struct string *self, const char *fmt, ...)
  85. {
  86. va_list args;
  87. const int capacity = string_capacity(self);
  88. va_start(args, fmt);
  89. const int len = vsnprintf(self->data + self->len, capacity, fmt, args);
  90. if (len >= capacity)
  91. {
  92. string_set_capacity(self, len + 16);
  93. // Some platforms require we va_end()/va_start() before we use args again
  94. va_end(args);
  95. va_start(args, fmt);
  96. vsnprintf(self->data + self->len, len + 1, fmt, args);
  97. }
  98. va_end(args);
  99. self->len += len;
  100. self->data[self->len] = '\0';
  101. }
  102. void vector_init(struct vector *self, const size_t is)
  103. {
  104. self->size = 0;
  105. self->len = 0;
  106. self->item_size = is;
  107. self->values = NULL;
  108. }
  109. void vector_dealloc(struct vector *self)
  110. {
  111. if (self->values)
  112. free(self->values);
  113. }
  114. void vector_set_capacity(struct vector *self, const size_t n)
  115. {
  116. const size_t c = self->size - self->len;
  117. if (c < n)
  118. {
  119. self->size += n - c;
  120. self->values = realloc(self->values, self->size * self->item_size);
  121. }
  122. }
  123. void *vector_pushnew(struct vector *self)
  124. {
  125. if (self->len == self->size)
  126. vector_set_capacity(self, 128);
  127. void *slot = vector_value(self, vector_size(self));
  128. self->len++;
  129. return slot;
  130. }
  131. void *vector_push(struct vector *self, const void *p)
  132. {
  133. void *out = vector_pushnew(self);
  134. memcpy(out, p, self->item_size);
  135. return out;
  136. }
  137. void *vector_pop(struct vector *self)
  138. {
  139. return vector_value(self, --self->len);
  140. }
  141. void vector_reset(struct vector *self)
  142. {
  143. self->len = 0;
  144. }
  145. void allocator_init(struct allocator *self, const size_t bc)
  146. {
  147. self->curBankUtilization= bc;
  148. self->curBank = NULL;
  149. self->curBanksIndex = 0;
  150. self->bankCapacity = bc;
  151. vector_init(&self->banks, sizeof(char *));
  152. }
  153. void allocator_dealloc(struct allocator *self)
  154. {
  155. while (vector_size(&self->banks))
  156. free(*(char **)vector_pop(&self->banks));
  157. vector_dealloc(&self->banks);
  158. }
  159. void *allocator_alloc(struct allocator *self, const size_t size)
  160. {
  161. if (self->curBankUtilization + size > self->bankCapacity)
  162. {
  163. if (self->curBanksIndex == vector_size(&self->banks))
  164. {
  165. self->curBank = (char *)malloc(self->bankCapacity);
  166. vector_push(&self->banks, &self->curBank);
  167. }
  168. else
  169. self->curBank = *(char **)vector_value(&self->banks, self->curBanksIndex);
  170. ++(self->curBanksIndex);
  171. self->curBankUtilization = size;
  172. return self->curBank;
  173. }
  174. char *ret = self->curBank + self->curBankUtilization;
  175. self->curBankUtilization+=size;
  176. return ret;
  177. }
  178. void allocator_reuse(struct allocator *self)
  179. {
  180. self->curBankUtilization= self->bankCapacity;
  181. self->curBank = NULL;
  182. self->curBanksIndex = 0;
  183. }
  184. #define LINELEN 76
  185. void base64_encode(uint8_t *data, size_t length, struct string *outputBuf, const int forHeaders)
  186. {
  187. unsigned int i;
  188. uint8_t dtable[256];
  189. for (i = 0; i < 9; i++)
  190. {
  191. dtable[i] = 'A' + i;
  192. dtable[i + 9] = 'J' + i;
  193. dtable[26 + i] = 'a' + i;
  194. dtable[26 + i + 9]= 'j' + i;
  195. }
  196. for (i = 0; i < 8; i++)
  197. {
  198. dtable[i + 18] = 'S' + i;
  199. dtable[26 + i + 18] = 's' + i;
  200. }
  201. for (i = 0; i < 10; i++)
  202. dtable[52 + i] = '0' + i;
  203. dtable[62] = '+';
  204. dtable[63] = '/';
  205. /* Make sure we have enough space to hold the base64 encoded data */
  206. uint32_t mm = length / 3 * 4, required = 32 + mm + (mm / LINELEN * 2);
  207. string_set_capacity(outputBuf, required);
  208. uint8_t *output = (uint8_t *)(string_data(outputBuf) + string_len(outputBuf)), *initial = output;
  209. int nChars = 0, lineLength = 0;
  210. uint8_t ig[3] = {0 , 0 , 0};
  211. while (length--)
  212. {
  213. if (nChars < 3)
  214. ig[nChars++] = *data++;
  215. else
  216. {
  217. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  218. *output++ = dtable[ig[0] >> 2];
  219. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  220. *output++ = dtable[((ig[0] & 3) << 4) | (ig[1] >> 4)];
  221. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  222. *output++ = dtable[((ig[1] & 0xf) << 2) | (ig[2] >> 6)];
  223. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  224. *output++ = dtable[ig[2] & 0x3f];
  225. nChars = 1;
  226. ig[0] = *data++;
  227. ig[1] = 0;
  228. ig[2] = 0;
  229. }
  230. }
  231. /* There bound to be some characters left to process */
  232. switch (nChars)
  233. {
  234. case 3:
  235. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  236. *output++ = dtable[ig[0] >> 2];
  237. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  238. *output++ = dtable[((ig[0] & 3) << 4) | (ig[1] >> 4)];
  239. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  240. *output++ = dtable[((ig[1] & 0xf) << 2) | (ig[2] >> 6)];
  241. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  242. *output++ = dtable[ig[2] & 0x3f];
  243. break;
  244. case 2:
  245. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  246. *output++ = dtable[ig[0] >> 2];
  247. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  248. *output++ = dtable[((ig[0] & 3) << 4) | (ig[1] >> 4)];
  249. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  250. *output++ = dtable[((ig[1] & 0xf) << 2) | (ig[2] >> 6)];
  251. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  252. *output++ = '=';
  253. break;
  254. case 1:
  255. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  256. *output++ = dtable[ig[0] >> 2];
  257. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  258. *output++ = dtable[((ig[0] & 3) << 4) | (ig[1] >> 4)];
  259. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  260. *output++ = '=';
  261. if (lineLength++ == LINELEN) { *output++ = '\r'; *output++ = '\n'; if (forHeaders) *output++ = '\t'; lineLength = 1; }
  262. *output++ = '=';
  263. break;
  264. }
  265. outputBuf->len = string_len(outputBuf) + (output - initial); // explicitly
  266. }
  267. #undef LINELEN