/src/amf.c

https://code.google.com/ · C · 1158 lines · 946 code · 124 blank · 88 comment · 246 complexity · 77aefa2886bbdcd52203b8808eafbfca MD5 · raw file

  1. /*
  2. $Id: amf.c 231 2011-06-27 13:46:19Z marc.noirot $
  3. FLV Metadata updater
  4. Copyright (C) 2007-2012 Marc Noirot <marc.noirot AT gmail.com>
  5. This file is part of FLVMeta.
  6. FLVMeta is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. FLVMeta is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with FLVMeta; if not, write to the Free Software
  16. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <string.h>
  19. #include "amf.h"
  20. /* function common to all array types */
  21. static void amf_list_init(amf_list * list) {
  22. if (list != NULL) {
  23. list->size = 0;
  24. list->first_element = NULL;
  25. list->last_element = NULL;
  26. }
  27. }
  28. static amf_data * amf_list_push(amf_list * list, amf_data * data) {
  29. amf_node * node = (amf_node*)malloc(sizeof(amf_node));
  30. if (node != NULL) {
  31. node->data = data;
  32. node->next = NULL;
  33. node->prev = NULL;
  34. if (list->size == 0) {
  35. list->first_element = node;
  36. list->last_element = node;
  37. }
  38. else {
  39. list->last_element->next = node;
  40. node->prev = list->last_element;
  41. list->last_element = node;
  42. }
  43. ++(list->size);
  44. return data;
  45. }
  46. return NULL;
  47. }
  48. static amf_data * amf_list_insert_before(amf_list * list, amf_node * node, amf_data * data) {
  49. if (node != NULL) {
  50. amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
  51. if (new_node != NULL) {
  52. new_node->next = node;
  53. new_node->prev = node->prev;
  54. if (node->prev != NULL) {
  55. node->prev->next = new_node;
  56. node->prev = new_node;
  57. }
  58. if (node == list->first_element) {
  59. list->first_element = new_node;
  60. }
  61. ++(list->size);
  62. new_node->data = data;
  63. return data;
  64. }
  65. }
  66. return NULL;
  67. }
  68. static amf_data * amf_list_insert_after(amf_list * list, amf_node * node, amf_data * data) {
  69. if (node != NULL) {
  70. amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
  71. if (new_node != NULL) {
  72. new_node->next = node->next;
  73. new_node->prev = node;
  74. if (node->next != NULL) {
  75. node->next->prev = new_node;
  76. node->next = new_node;
  77. }
  78. if (node == list->last_element) {
  79. list->last_element = new_node;
  80. }
  81. ++(list->size);
  82. new_node->data = data;
  83. return data;
  84. }
  85. }
  86. return NULL;
  87. }
  88. static amf_data * amf_list_delete(amf_list * list, amf_node * node) {
  89. amf_data * data = NULL;
  90. if (node != NULL) {
  91. if (node->next != NULL) {
  92. node->next->prev = node->prev;
  93. }
  94. if (node->prev != NULL) {
  95. node->prev->next = node->next;
  96. }
  97. if (node == list->first_element) {
  98. list->first_element = node->next;
  99. }
  100. if (node == list->last_element) {
  101. list->last_element = node->prev;
  102. }
  103. data = node->data;
  104. free(node);
  105. --(list->size);
  106. }
  107. return data;
  108. }
  109. static amf_data * amf_list_get_at(const amf_list * list, uint32 n) {
  110. if (n < list->size) {
  111. uint32 i;
  112. amf_node * node = list->first_element;
  113. for (i = 0; i < n; ++i) {
  114. node = node->next;
  115. }
  116. return node->data;
  117. }
  118. return NULL;
  119. }
  120. static amf_data * amf_list_pop(amf_list * list) {
  121. return amf_list_delete(list, list->last_element);
  122. }
  123. static amf_node * amf_list_first(const amf_list * list) {
  124. return list->first_element;
  125. }
  126. static amf_node * amf_list_last(const amf_list * list) {
  127. return list->last_element;
  128. }
  129. static void amf_list_clear(amf_list * list) {
  130. amf_node * tmp;
  131. amf_node * node = list->first_element;
  132. while (node != NULL) {
  133. amf_data_free(node->data);
  134. tmp = node;
  135. node = node->next;
  136. free(tmp);
  137. }
  138. list->size = 0;
  139. }
  140. static amf_list * amf_list_clone(const amf_list * list, amf_list * out_list) {
  141. amf_node * node;
  142. node = list->first_element;
  143. while (node != NULL) {
  144. amf_list_push(out_list, amf_data_clone(node->data));
  145. node = node->next;
  146. }
  147. return out_list;
  148. }
  149. /* structure used to mimic a stream with a memory buffer */
  150. typedef struct __buffer_context {
  151. byte * start_address;
  152. byte * current_address;
  153. size_t buffer_size;
  154. } buffer_context;
  155. /* callback function to mimic fread using a memory buffer */
  156. static size_t buffer_read(void * out_buffer, size_t size, void * user_data) {
  157. buffer_context * ctxt = (buffer_context *)user_data;
  158. if (ctxt->current_address >= ctxt->start_address &&
  159. ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
  160. memcpy(out_buffer, ctxt->current_address, size);
  161. ctxt->current_address += size;
  162. return size;
  163. }
  164. else {
  165. return 0;
  166. }
  167. }
  168. /* callback function to mimic fwrite using a memory buffer */
  169. static size_t buffer_write(const void * in_buffer, size_t size, void * user_data) {
  170. buffer_context * ctxt = (buffer_context *)user_data;
  171. if (ctxt->current_address >= ctxt->start_address &&
  172. ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
  173. memcpy(ctxt->current_address, in_buffer, size);
  174. ctxt->current_address += size;
  175. return size;
  176. }
  177. else {
  178. return 0;
  179. }
  180. }
  181. /* allocate an AMF data object */
  182. amf_data * amf_data_new(byte type) {
  183. amf_data * data = (amf_data*)malloc(sizeof(amf_data));
  184. if (data != NULL) {
  185. data->type = type;
  186. data->error_code = AMF_ERROR_OK;
  187. }
  188. return data;
  189. }
  190. /* read AMF data from buffer */
  191. amf_data * amf_data_buffer_read(byte * buffer, size_t maxbytes) {
  192. buffer_context ctxt;
  193. ctxt.start_address = ctxt.current_address = buffer;
  194. ctxt.buffer_size = maxbytes;
  195. return amf_data_read(buffer_read, &ctxt);
  196. }
  197. /* write AMF data to buffer */
  198. size_t amf_data_buffer_write(amf_data * data, byte * buffer, size_t maxbytes) {
  199. buffer_context ctxt;
  200. ctxt.start_address = ctxt.current_address = buffer;
  201. ctxt.buffer_size = maxbytes;
  202. return amf_data_write(data, buffer_write, &ctxt);
  203. }
  204. /* callback function to read data from a file stream */
  205. static size_t file_read(void * out_buffer, size_t size, void * user_data) {
  206. return fread(out_buffer, sizeof(byte), size, (FILE *)user_data);
  207. }
  208. /* callback function to write data to a file stream */
  209. static size_t file_write(const void * in_buffer, size_t size, void * user_data) {
  210. return fwrite(in_buffer, sizeof(byte), size, (FILE *)user_data);
  211. }
  212. /* load AMF data from a file stream */
  213. amf_data * amf_data_file_read(FILE * stream) {
  214. return amf_data_read(file_read, stream);
  215. }
  216. /* write AMF data into a file stream */
  217. size_t amf_data_file_write(const amf_data * data, FILE * stream) {
  218. return amf_data_write(data, file_write, stream);
  219. }
  220. /* read a number */
  221. static amf_data * amf_number_read(amf_read_proc read_proc, void * user_data) {
  222. number64_be val;
  223. if (read_proc(&val, sizeof(number64_be), user_data) == sizeof(number64_be)) {
  224. return amf_number_new(swap_number64(val));
  225. }
  226. else {
  227. return amf_data_error(AMF_ERROR_EOF);
  228. }
  229. }
  230. /* read a boolean */
  231. static amf_data * amf_boolean_read(amf_read_proc read_proc, void * user_data) {
  232. uint8 val;
  233. if (read_proc(&val, sizeof(uint8), user_data) == sizeof(uint8)) {
  234. return amf_boolean_new(val);
  235. }
  236. else {
  237. return amf_data_error(AMF_ERROR_EOF);
  238. }
  239. }
  240. /* read a string */
  241. static amf_data * amf_string_read(amf_read_proc read_proc, void * user_data) {
  242. uint16_be strsize;
  243. byte * buffer;
  244. if (read_proc(&strsize, sizeof(uint16_be), user_data) < sizeof(uint16_be)) {
  245. return amf_data_error(AMF_ERROR_EOF);
  246. }
  247. strsize = swap_uint16(strsize);
  248. if (strsize == 0) {
  249. return amf_string_new(NULL, 0);
  250. }
  251. buffer = (byte*)calloc(strsize, sizeof(byte));
  252. if (buffer == NULL) {
  253. return NULL;
  254. }
  255. if (read_proc(buffer, strsize, user_data) == strsize) {
  256. amf_data * data = amf_string_new(buffer, strsize);
  257. free(buffer);
  258. return data;
  259. }
  260. else {
  261. free(buffer);
  262. return amf_data_error(AMF_ERROR_EOF);
  263. }
  264. }
  265. /* read an object */
  266. static amf_data * amf_object_read(amf_read_proc read_proc, void * user_data) {
  267. amf_data * name;
  268. amf_data * element;
  269. byte error_code;
  270. amf_data * data;
  271. data = amf_object_new();
  272. if (data == NULL) {
  273. return NULL;
  274. }
  275. while (1) {
  276. name = amf_string_read(read_proc, user_data);
  277. error_code = amf_data_get_error_code(name);
  278. if (error_code != AMF_ERROR_OK) {
  279. /* invalid name: error */
  280. amf_data_free(name);
  281. amf_data_free(data);
  282. return amf_data_error(error_code);
  283. }
  284. element = amf_data_read(read_proc, user_data);
  285. error_code = amf_data_get_error_code(element);
  286. if (error_code == AMF_ERROR_END_TAG || error_code == AMF_ERROR_UNKNOWN_TYPE) {
  287. /* end tag or unknown element: end of data, exit loop */
  288. amf_data_free(name);
  289. amf_data_free(element);
  290. break;
  291. }
  292. else if (error_code != AMF_ERROR_OK) {
  293. amf_data_free(name);
  294. amf_data_free(data);
  295. amf_data_free(element);
  296. return amf_data_error(error_code);
  297. }
  298. if (amf_object_add(data, (char *)amf_string_get_bytes(name), element) == NULL) {
  299. amf_data_free(name);
  300. amf_data_free(element);
  301. amf_data_free(data);
  302. return NULL;
  303. }
  304. else {
  305. amf_data_free(name);
  306. }
  307. }
  308. return data;
  309. }
  310. /* read an associative array */
  311. static amf_data * amf_associative_array_read(amf_read_proc read_proc, void * user_data) {
  312. amf_data * name;
  313. amf_data * element;
  314. uint32_be size;
  315. byte error_code;
  316. amf_data * data;
  317. data = amf_associative_array_new();
  318. if (data == NULL) {
  319. return NULL;
  320. }
  321. /* we ignore the 32 bits array size marker */
  322. if (read_proc(&size, sizeof(uint32_be), user_data) < sizeof(uint32_be)) {
  323. amf_data_free(data);
  324. return amf_data_error(AMF_ERROR_EOF);
  325. }
  326. while(1) {
  327. name = amf_string_read(read_proc, user_data);
  328. error_code = amf_data_get_error_code(name);
  329. if (error_code != AMF_ERROR_OK) {
  330. /* invalid name: error */
  331. amf_data_free(name);
  332. amf_data_free(data);
  333. return amf_data_error(error_code);
  334. }
  335. element = amf_data_read(read_proc, user_data);
  336. error_code = amf_data_get_error_code(element);
  337. if (amf_string_get_size(name) == 0 || error_code == AMF_ERROR_END_TAG || error_code == AMF_ERROR_UNKNOWN_TYPE) {
  338. /* end tag or unknown element: end of data, exit loop */
  339. amf_data_free(name);
  340. amf_data_free(element);
  341. break;
  342. }
  343. else if (error_code != AMF_ERROR_OK) {
  344. amf_data_free(name);
  345. amf_data_free(data);
  346. amf_data_free(element);
  347. return amf_data_error(error_code);
  348. }
  349. if (amf_associative_array_add(data, (char *)amf_string_get_bytes(name), element) == NULL) {
  350. amf_data_free(name);
  351. amf_data_free(element);
  352. amf_data_free(data);
  353. return NULL;
  354. }
  355. else {
  356. amf_data_free(name);
  357. }
  358. }
  359. return data;
  360. }
  361. /* read an array */
  362. static amf_data * amf_array_read(amf_read_proc read_proc, void * user_data) {
  363. size_t i;
  364. amf_data * element;
  365. byte error_code;
  366. amf_data * data;
  367. uint32 array_size;
  368. data = amf_array_new();
  369. if (data == NULL) {
  370. return NULL;
  371. }
  372. if (read_proc(&array_size, sizeof(uint32), user_data) < sizeof(uint32)) {
  373. amf_data_free(data);
  374. return amf_data_error(AMF_ERROR_EOF);
  375. }
  376. array_size = swap_uint32(array_size);
  377. for (i = 0; i < array_size; ++i) {
  378. element = amf_data_read(read_proc, user_data);
  379. error_code = amf_data_get_error_code(element);
  380. if (error_code != AMF_ERROR_OK) {
  381. amf_data_free(element);
  382. amf_data_free(data);
  383. return amf_data_error(error_code);
  384. }
  385. if (amf_array_push(data, element) == NULL) {
  386. amf_data_free(element);
  387. amf_data_free(data);
  388. return NULL;
  389. }
  390. }
  391. return data;
  392. }
  393. /* read a date */
  394. static amf_data * amf_date_read(amf_read_proc read_proc, void * user_data) {
  395. number64_be milliseconds;
  396. sint16_be timezone;
  397. if (read_proc(&milliseconds, sizeof(number64_be), user_data) == sizeof(number64_be) &&
  398. read_proc(&timezone, sizeof(sint16_be), user_data) == sizeof(sint16_be)) {
  399. return amf_date_new(swap_number64(milliseconds), swap_sint16(timezone));
  400. }
  401. else {
  402. return amf_data_error(AMF_ERROR_EOF);
  403. }
  404. }
  405. /* load AMF data from stream */
  406. amf_data * amf_data_read(amf_read_proc read_proc, void * user_data) {
  407. byte type;
  408. if (read_proc(&type, sizeof(byte), user_data) < sizeof(byte)) {
  409. return amf_data_error(AMF_ERROR_EOF);
  410. }
  411. switch (type) {
  412. case AMF_TYPE_NUMBER:
  413. return amf_number_read(read_proc, user_data);
  414. case AMF_TYPE_BOOLEAN:
  415. return amf_boolean_read(read_proc, user_data);
  416. case AMF_TYPE_STRING:
  417. return amf_string_read(read_proc, user_data);
  418. case AMF_TYPE_OBJECT:
  419. return amf_object_read(read_proc, user_data);
  420. case AMF_TYPE_NULL:
  421. return amf_null_new();
  422. case AMF_TYPE_UNDEFINED:
  423. return amf_undefined_new();
  424. /*case AMF_TYPE_REFERENCE:*/
  425. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  426. return amf_associative_array_read(read_proc, user_data);
  427. case AMF_TYPE_ARRAY:
  428. return amf_array_read(read_proc, user_data);
  429. case AMF_TYPE_DATE:
  430. return amf_date_read(read_proc, user_data);
  431. /*case AMF_TYPE_SIMPLEOBJECT:*/
  432. case AMF_TYPE_XML:
  433. case AMF_TYPE_CLASS:
  434. return amf_data_error(AMF_ERROR_UNSUPPORTED_TYPE);
  435. case AMF_TYPE_END:
  436. return amf_data_error(AMF_ERROR_END_TAG); /* end of composite object */
  437. default:
  438. return amf_data_error(AMF_ERROR_UNKNOWN_TYPE);
  439. }
  440. }
  441. /* determines the size of the given AMF data */
  442. size_t amf_data_size(const amf_data * data) {
  443. size_t s = 0;
  444. amf_node * node;
  445. if (data != NULL) {
  446. s += sizeof(byte);
  447. switch (data->type) {
  448. case AMF_TYPE_NUMBER:
  449. s += sizeof(number64_be);
  450. break;
  451. case AMF_TYPE_BOOLEAN:
  452. s += sizeof(uint8);
  453. break;
  454. case AMF_TYPE_STRING:
  455. s += sizeof(uint16) + (size_t)amf_string_get_size(data);
  456. break;
  457. case AMF_TYPE_OBJECT:
  458. node = amf_object_first(data);
  459. while (node != NULL) {
  460. s += sizeof(uint16) + (size_t)amf_string_get_size(amf_object_get_name(node));
  461. s += (size_t)amf_data_size(amf_object_get_data(node));
  462. node = amf_object_next(node);
  463. }
  464. s += sizeof(uint16) + sizeof(uint8);
  465. break;
  466. case AMF_TYPE_NULL:
  467. case AMF_TYPE_UNDEFINED:
  468. break;
  469. /*case AMF_TYPE_REFERENCE:*/
  470. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  471. s += sizeof(uint32);
  472. node = amf_associative_array_first(data);
  473. while (node != NULL) {
  474. s += sizeof(uint16) + (size_t)amf_string_get_size(amf_associative_array_get_name(node));
  475. s += (size_t)amf_data_size(amf_associative_array_get_data(node));
  476. node = amf_associative_array_next(node);
  477. }
  478. s += sizeof(uint16) + sizeof(uint8);
  479. break;
  480. case AMF_TYPE_ARRAY:
  481. s += sizeof(uint32);
  482. node = amf_array_first(data);
  483. while (node != NULL) {
  484. s += (size_t)amf_data_size(amf_array_get(node));
  485. node = amf_array_next(node);
  486. }
  487. break;
  488. case AMF_TYPE_DATE:
  489. s += sizeof(number64) + sizeof(sint16);
  490. break;
  491. /*case AMF_TYPE_SIMPLEOBJECT:*/
  492. case AMF_TYPE_XML:
  493. case AMF_TYPE_CLASS:
  494. case AMF_TYPE_END:
  495. break; /* end of composite object */
  496. default:
  497. break;
  498. }
  499. }
  500. return s;
  501. }
  502. /* write a number */
  503. static size_t amf_number_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  504. number64 n = swap_number64(data->number_data);
  505. return write_proc(&n, sizeof(number64_be), user_data);
  506. }
  507. /* write a boolean */
  508. static size_t amf_boolean_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  509. return write_proc(&(data->boolean_data), sizeof(uint8), user_data);
  510. }
  511. /* write a string */
  512. static size_t amf_string_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  513. uint16 s;
  514. size_t w = 0;
  515. s = swap_uint16(data->string_data.size);
  516. w = write_proc(&s, sizeof(uint16_be), user_data);
  517. if (data->string_data.size > 0) {
  518. w += write_proc(data->string_data.mbstr, (size_t)(data->string_data.size), user_data);
  519. }
  520. return w;
  521. }
  522. /* write an object */
  523. static size_t amf_object_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  524. amf_node * node;
  525. size_t w = 0;
  526. uint16_be filler = swap_uint16(0);
  527. uint8 terminator = AMF_TYPE_END;
  528. node = amf_object_first(data);
  529. while (node != NULL) {
  530. w += amf_string_write(amf_object_get_name(node), write_proc, user_data);
  531. w += amf_data_write(amf_object_get_data(node), write_proc, user_data);
  532. node = amf_object_next(node);
  533. }
  534. /* empty string is the last element */
  535. w += write_proc(&filler, sizeof(uint16_be), user_data);
  536. /* an object ends with 0x09 */
  537. w += write_proc(&terminator, sizeof(uint8), user_data);
  538. return w;
  539. }
  540. /* write an associative array */
  541. static size_t amf_associative_array_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  542. amf_node * node;
  543. size_t w = 0;
  544. uint32_be s;
  545. uint16_be filler = swap_uint16(0);
  546. uint8 terminator = AMF_TYPE_END;
  547. s = swap_uint32(data->list_data.size) / 2;
  548. w += write_proc(&s, sizeof(uint32_be), user_data);
  549. node = amf_associative_array_first(data);
  550. while (node != NULL) {
  551. w += amf_string_write(amf_associative_array_get_name(node), write_proc, user_data);
  552. w += amf_data_write(amf_associative_array_get_data(node), write_proc, user_data);
  553. node = amf_associative_array_next(node);
  554. }
  555. /* empty string is the last element */
  556. w += write_proc(&filler, sizeof(uint16_be), user_data);
  557. /* an object ends with 0x09 */
  558. w += write_proc(&terminator, sizeof(uint8), user_data);
  559. return w;
  560. }
  561. /* write an array */
  562. static size_t amf_array_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  563. amf_node * node;
  564. size_t w = 0;
  565. uint32_be s;
  566. s = swap_uint32(data->list_data.size);
  567. w += write_proc(&s, sizeof(uint32_be), user_data);
  568. node = amf_array_first(data);
  569. while (node != NULL) {
  570. w += amf_data_write(amf_array_get(node), write_proc, user_data);
  571. node = amf_array_next(node);
  572. }
  573. return w;
  574. }
  575. /* write a date */
  576. static size_t amf_date_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  577. size_t w = 0;
  578. number64_be milli;
  579. sint16_be tz;
  580. milli = swap_number64(data->date_data.milliseconds);
  581. w += write_proc(&milli, sizeof(number64_be), user_data);
  582. tz = swap_sint16(data->date_data.timezone);
  583. w += write_proc(&tz, sizeof(sint16_be), user_data);
  584. return w;
  585. }
  586. /* write amf data to stream */
  587. size_t amf_data_write(const amf_data * data, amf_write_proc write_proc, void * user_data) {
  588. size_t s = 0;
  589. if (data != NULL) {
  590. s += write_proc(&(data->type), sizeof(byte), user_data);
  591. switch (data->type) {
  592. case AMF_TYPE_NUMBER:
  593. s += amf_number_write(data, write_proc, user_data);
  594. break;
  595. case AMF_TYPE_BOOLEAN:
  596. s += amf_boolean_write(data, write_proc, user_data);
  597. break;
  598. case AMF_TYPE_STRING:
  599. s += amf_string_write(data, write_proc, user_data);
  600. break;
  601. case AMF_TYPE_OBJECT:
  602. s += amf_object_write(data, write_proc, user_data);
  603. break;
  604. case AMF_TYPE_NULL:
  605. case AMF_TYPE_UNDEFINED:
  606. break;
  607. /*case AMF_TYPE_REFERENCE:*/
  608. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  609. s += amf_associative_array_write(data, write_proc, user_data);
  610. break;
  611. case AMF_TYPE_ARRAY:
  612. s += amf_array_write(data, write_proc, user_data);
  613. break;
  614. case AMF_TYPE_DATE:
  615. s += amf_date_write(data, write_proc, user_data);
  616. break;
  617. /*case AMF_TYPE_SIMPLEOBJECT:*/
  618. case AMF_TYPE_XML:
  619. case AMF_TYPE_CLASS:
  620. case AMF_TYPE_END:
  621. break; /* end of composite object */
  622. default:
  623. break;
  624. }
  625. }
  626. return s;
  627. }
  628. /* data type */
  629. byte amf_data_get_type(const amf_data * data) {
  630. return (data != NULL) ? data->type : AMF_TYPE_NULL;
  631. }
  632. /* error code */
  633. byte amf_data_get_error_code(const amf_data * data) {
  634. return (data != NULL) ? data->error_code : AMF_ERROR_NULL_POINTER;
  635. }
  636. /* clone AMF data */
  637. amf_data * amf_data_clone(const amf_data * data) {
  638. /* we copy data recursively */
  639. if (data != NULL) {
  640. switch (data->type) {
  641. case AMF_TYPE_NUMBER: return amf_number_new(amf_number_get_value(data));
  642. case AMF_TYPE_BOOLEAN: return amf_boolean_new(amf_boolean_get_value(data));
  643. case AMF_TYPE_STRING:
  644. if (data->string_data.mbstr != NULL) {
  645. return amf_string_new((byte *)strdup((char *)amf_string_get_bytes(data)), amf_string_get_size(data));
  646. }
  647. else {
  648. return amf_str(NULL);
  649. }
  650. case AMF_TYPE_NULL: return NULL;
  651. case AMF_TYPE_UNDEFINED: return NULL;
  652. /*case AMF_TYPE_REFERENCE:*/
  653. case AMF_TYPE_OBJECT:
  654. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  655. case AMF_TYPE_ARRAY:
  656. {
  657. amf_data * d = amf_data_new(data->type);
  658. if (d != NULL) {
  659. amf_list_init(&d->list_data);
  660. amf_list_clone(&data->list_data, &d->list_data);
  661. }
  662. return d;
  663. }
  664. case AMF_TYPE_DATE: return amf_date_new(amf_date_get_milliseconds(data), amf_date_get_timezone(data));
  665. /*case AMF_TYPE_SIMPLEOBJECT:*/
  666. case AMF_TYPE_XML: return NULL;
  667. case AMF_TYPE_CLASS: return NULL;
  668. }
  669. }
  670. return NULL;
  671. }
  672. /* free AMF data */
  673. void amf_data_free(amf_data * data) {
  674. if (data != NULL) {
  675. switch (data->type) {
  676. case AMF_TYPE_NUMBER: break;
  677. case AMF_TYPE_BOOLEAN: break;
  678. case AMF_TYPE_STRING:
  679. if (data->string_data.mbstr != NULL) {
  680. free(data->string_data.mbstr);
  681. } break;
  682. case AMF_TYPE_NULL: break;
  683. case AMF_TYPE_UNDEFINED: break;
  684. /*case AMF_TYPE_REFERENCE:*/
  685. case AMF_TYPE_OBJECT:
  686. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  687. case AMF_TYPE_ARRAY: amf_list_clear(&data->list_data); break;
  688. case AMF_TYPE_DATE: break;
  689. /*case AMF_TYPE_SIMPLEOBJECT:*/
  690. case AMF_TYPE_XML: break;
  691. case AMF_TYPE_CLASS: break;
  692. default: break;
  693. }
  694. free(data);
  695. }
  696. }
  697. /* dump AMF data into a stream as text */
  698. void amf_data_dump(FILE * stream, const amf_data * data, int indent_level) {
  699. if (data != NULL) {
  700. amf_node * node;
  701. time_t time;
  702. struct tm * t;
  703. char datestr[128];
  704. switch (data->type) {
  705. case AMF_TYPE_NUMBER:
  706. fprintf(stream, "%.12g", data->number_data);
  707. break;
  708. case AMF_TYPE_BOOLEAN:
  709. fprintf(stream, "%s", (data->boolean_data) ? "true" : "false");
  710. break;
  711. case AMF_TYPE_STRING:
  712. fprintf(stream, "\'%.*s\'", data->string_data.size, data->string_data.mbstr);
  713. break;
  714. case AMF_TYPE_OBJECT:
  715. node = amf_object_first(data);
  716. fprintf(stream, "{\n");
  717. while (node != NULL) {
  718. fprintf(stream, "%*s", (indent_level+1)*4, "");
  719. amf_data_dump(stream, amf_object_get_name(node), indent_level+1);
  720. fprintf(stream, ": ");
  721. amf_data_dump(stream, amf_object_get_data(node), indent_level+1);
  722. node = amf_object_next(node);
  723. fprintf(stream, "\n");
  724. }
  725. fprintf(stream, "%*s", indent_level*4 + 1, "}");
  726. break;
  727. case AMF_TYPE_NULL:
  728. fprintf(stream, "null");
  729. break;
  730. case AMF_TYPE_UNDEFINED:
  731. fprintf(stream, "undefined");
  732. break;
  733. /*case AMF_TYPE_REFERENCE:*/
  734. case AMF_TYPE_ASSOCIATIVE_ARRAY:
  735. node = amf_associative_array_first(data);
  736. fprintf(stream, "{\n");
  737. while (node != NULL) {
  738. fprintf(stream, "%*s", (indent_level+1)*4, "");
  739. amf_data_dump(stream, amf_associative_array_get_name(node), indent_level+1);
  740. fprintf(stream, " => ");
  741. amf_data_dump(stream, amf_associative_array_get_data(node), indent_level+1);
  742. node = amf_associative_array_next(node);
  743. fprintf(stream, "\n");
  744. }
  745. fprintf(stream, "%*s", indent_level*4 + 1, "}");
  746. break;
  747. case AMF_TYPE_ARRAY:
  748. node = amf_array_first(data);
  749. fprintf(stream, "[\n");
  750. while (node != NULL) {
  751. fprintf(stream, "%*s", (indent_level+1)*4, "");
  752. amf_data_dump(stream, node->data, indent_level+1);
  753. node = amf_array_next(node);
  754. fprintf(stream, "\n");
  755. }
  756. fprintf(stream, "%*s", indent_level*4 + 1, "]");
  757. break;
  758. case AMF_TYPE_DATE:
  759. time = amf_date_to_time_t(data);
  760. tzset();
  761. t = localtime(&time);
  762. strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S %z", t);
  763. fprintf(stream, "%s", datestr);
  764. break;
  765. /*case AMF_TYPE_SIMPLEOBJECT:*/
  766. case AMF_TYPE_XML: break;
  767. case AMF_TYPE_CLASS: break;
  768. default: break;
  769. }
  770. }
  771. }
  772. /* return a null AMF object with the specified error code attached to it */
  773. amf_data * amf_data_error(byte error_code) {
  774. amf_data * data = amf_null_new();
  775. if (data != NULL) {
  776. data->error_code = error_code;
  777. }
  778. return data;
  779. }
  780. /* number functions */
  781. amf_data * amf_number_new(number64 value) {
  782. amf_data * data = amf_data_new(AMF_TYPE_NUMBER);
  783. if (data != NULL) {
  784. data->number_data = value;
  785. }
  786. return data;
  787. }
  788. number64 amf_number_get_value(const amf_data * data) {
  789. return (data != NULL) ? data->number_data : 0;
  790. }
  791. void amf_number_set_value(amf_data * data, number64 value) {
  792. if (data != NULL) {
  793. data->number_data = value;
  794. }
  795. }
  796. /* boolean functions */
  797. amf_data * amf_boolean_new(uint8 value) {
  798. amf_data * data = amf_data_new(AMF_TYPE_BOOLEAN);
  799. if (data != NULL) {
  800. data->boolean_data = value;
  801. }
  802. return data;
  803. }
  804. uint8 amf_boolean_get_value(const amf_data * data) {
  805. return (data != NULL) ? data->boolean_data : 0;
  806. }
  807. void amf_boolean_set_value(amf_data * data, uint8 value) {
  808. if (data != NULL) {
  809. data->boolean_data = value;
  810. }
  811. }
  812. /* string functions */
  813. amf_data * amf_string_new(byte * str, uint16 size) {
  814. amf_data * data = amf_data_new(AMF_TYPE_STRING);
  815. if (data != NULL) {
  816. if (str == NULL) {
  817. data->string_data.size = 0;
  818. }
  819. else {
  820. data->string_data.size = size;
  821. }
  822. data->string_data.mbstr = (byte*)calloc(size+1, sizeof(byte));
  823. if (data->string_data.mbstr != NULL) {
  824. if (data->string_data.size > 0) {
  825. memcpy(data->string_data.mbstr, str, data->string_data.size);
  826. }
  827. }
  828. else {
  829. amf_data_free(data);
  830. return NULL;
  831. }
  832. }
  833. return data;
  834. }
  835. amf_data * amf_str(const char * str) {
  836. return amf_string_new((byte *)str, (uint16)(str != NULL ? strlen(str) : 0));
  837. }
  838. uint16 amf_string_get_size(const amf_data * data) {
  839. return (data != NULL) ? data->string_data.size : 0;
  840. }
  841. byte * amf_string_get_bytes(const amf_data * data) {
  842. return (data != NULL) ? data->string_data.mbstr : NULL;
  843. }
  844. /* object functions */
  845. amf_data * amf_object_new(void) {
  846. amf_data * data = amf_data_new(AMF_TYPE_OBJECT);
  847. if (data != NULL) {
  848. amf_list_init(&data->list_data);
  849. }
  850. return data;
  851. }
  852. uint32 amf_object_size(const amf_data * data) {
  853. return (data != NULL) ? data->list_data.size / 2 : 0;
  854. }
  855. amf_data * amf_object_add(amf_data * data, const char * name, amf_data * element) {
  856. if (data != NULL) {
  857. if (amf_list_push(&data->list_data, amf_str(name)) != NULL) {
  858. if (amf_list_push(&data->list_data, element) != NULL) {
  859. return element;
  860. }
  861. else {
  862. amf_data_free(amf_list_pop(&data->list_data));
  863. }
  864. }
  865. }
  866. return NULL;
  867. }
  868. amf_data * amf_object_get(const amf_data * data, const char * name) {
  869. if (data != NULL) {
  870. amf_node * node = amf_list_first(&(data->list_data));
  871. while (node != NULL) {
  872. if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
  873. node = node->next;
  874. return (node != NULL) ? node->data : NULL;
  875. }
  876. /* we have to skip the element data to reach the next name */
  877. node = node->next->next;
  878. }
  879. }
  880. return NULL;
  881. }
  882. amf_data * amf_object_set(amf_data * data, const char * name, amf_data * element) {
  883. if (data != NULL) {
  884. amf_node * node = amf_list_first(&(data->list_data));
  885. while (node != NULL) {
  886. if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
  887. node = node->next;
  888. if (node != NULL && node->data != NULL) {
  889. amf_data_free(node->data);
  890. node->data = element;
  891. return element;
  892. }
  893. }
  894. /* we have to skip the element data to reach the next name */
  895. node = node->next->next;
  896. }
  897. }
  898. return NULL;
  899. }
  900. amf_data * amf_object_delete(amf_data * data, const char * name) {
  901. if (data != NULL) {
  902. amf_node * node = amf_list_first(&data->list_data);
  903. while (node != NULL) {
  904. node = node->next;
  905. if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
  906. amf_node * data_node = node->next;
  907. amf_data_free(amf_list_delete(&data->list_data, node));
  908. return amf_list_delete(&data->list_data, data_node);
  909. }
  910. else {
  911. node = node->next;
  912. }
  913. }
  914. }
  915. return NULL;
  916. }
  917. amf_node * amf_object_first(const amf_data * data) {
  918. return (data != NULL) ? amf_list_first(&data->list_data) : NULL;
  919. }
  920. amf_node * amf_object_last(const amf_data * data) {
  921. if (data != NULL) {
  922. amf_node * node = amf_list_last(&data->list_data);
  923. if (node != NULL) {
  924. return node->prev;
  925. }
  926. }
  927. return NULL;
  928. }
  929. amf_node * amf_object_next(amf_node * node) {
  930. if (node != NULL) {
  931. amf_node * next = node->next;
  932. if (next != NULL) {
  933. return next->next;
  934. }
  935. }
  936. return NULL;
  937. }
  938. amf_node * amf_object_prev(amf_node * node) {
  939. if (node != NULL) {
  940. amf_node * prev = node->prev;
  941. if (prev != NULL) {
  942. return prev->prev;
  943. }
  944. }
  945. return NULL;
  946. }
  947. amf_data * amf_object_get_name(amf_node * node) {
  948. return (node != NULL) ? node->data : NULL;
  949. }
  950. amf_data * amf_object_get_data(amf_node * node) {
  951. if (node != NULL) {
  952. amf_node * next = node->next;
  953. if (next != NULL) {
  954. return next->data;
  955. }
  956. }
  957. return NULL;
  958. }
  959. /* associative array functions */
  960. amf_data * amf_associative_array_new(void) {
  961. amf_data * data = amf_data_new(AMF_TYPE_ASSOCIATIVE_ARRAY);
  962. if (data != NULL) {
  963. amf_list_init(&data->list_data);
  964. }
  965. return data;
  966. }
  967. /* array functions */
  968. amf_data * amf_array_new(void) {
  969. amf_data * data = amf_data_new(AMF_TYPE_ARRAY);
  970. if (data != NULL) {
  971. amf_list_init(&data->list_data);
  972. }
  973. return data;
  974. }
  975. uint32 amf_array_size(const amf_data * data) {
  976. return (data != NULL) ? data->list_data.size : 0;
  977. }
  978. amf_data * amf_array_push(amf_data * data, amf_data * element) {
  979. return (data != NULL) ? amf_list_push(&data->list_data, element) : NULL;
  980. }
  981. amf_data * amf_array_pop(amf_data * data) {
  982. return (data != NULL) ? amf_list_pop(&data->list_data) : NULL;
  983. }
  984. amf_node * amf_array_first(const amf_data * data) {
  985. return (data != NULL) ? amf_list_first(&data->list_data) : NULL;
  986. }
  987. amf_node * amf_array_last(const amf_data * data) {
  988. return (data != NULL) ? amf_list_last(&data->list_data) : NULL;
  989. }
  990. amf_node * amf_array_next(amf_node * node) {
  991. return (node != NULL) ? node->next : NULL;
  992. }
  993. amf_node * amf_array_prev(amf_node * node) {
  994. return (node != NULL) ? node->prev : NULL;
  995. }
  996. amf_data * amf_array_get(amf_node * node) {
  997. return (node != NULL) ? node->data : NULL;
  998. }
  999. amf_data * amf_array_get_at(const amf_data * data, uint32 n) {
  1000. return (data != NULL) ? amf_list_get_at(&data->list_data, n) : NULL;
  1001. }
  1002. amf_data * amf_array_delete(amf_data * data, amf_node * node) {
  1003. return (data != NULL) ? amf_list_delete(&data->list_data, node) : NULL;
  1004. }
  1005. amf_data * amf_array_insert_before(amf_data * data, amf_node * node, amf_data * element) {
  1006. return (data != NULL) ? amf_list_insert_before(&data->list_data, node, element) : NULL;
  1007. }
  1008. amf_data * amf_array_insert_after(amf_data * data, amf_node * node, amf_data * element) {
  1009. return (data != NULL) ? amf_list_insert_after(&data->list_data, node, element) : NULL;
  1010. }
  1011. /* date functions */
  1012. amf_data * amf_date_new(number64 milliseconds, sint16 timezone) {
  1013. amf_data * data = amf_data_new(AMF_TYPE_DATE);
  1014. if (data != NULL) {
  1015. data->date_data.milliseconds = milliseconds;
  1016. data->date_data.timezone = timezone;
  1017. }
  1018. return data;
  1019. }
  1020. number64 amf_date_get_milliseconds(const amf_data * data) {
  1021. return (data != NULL) ? data->date_data.milliseconds : 0.0;
  1022. }
  1023. sint16 amf_date_get_timezone(const amf_data * data) {
  1024. return (data != NULL) ? data->date_data.timezone : 0;
  1025. }
  1026. time_t amf_date_to_time_t(const amf_data * data) {
  1027. return (time_t)((data != NULL) ? data->date_data.milliseconds / 1000 : 0);
  1028. }