Advertisement
Guest User

Untitled

a guest
May 8th, 2013
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.50 KB | None | 0 0
  1. /* $Id: pack.c,v 1.40.2.7 2005/01/25 22:52:19 iliaa Exp $ */
  2.  
  3. #include "php.h"
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <fcntl.h>
  11. #ifdef PHP_WIN32
  12. #include <windows.h>
  13. #include <winsock.h>
  14. #define O_RDONLY _O_RDONLY
  15. #include "win32/param.h"
  16. #elif defined(NETWARE)
  17. #ifdef USE_WINSOCK
  18. /*#include <ws2nlm.h>*/
  19. #include <novsock2.h>
  20. #else
  21. #include <sys/socket.h>
  22. #endif
  23. #ifdef NEW_LIBC
  24. #include <sys/param.h>
  25. #else
  26. #include "netware/param.h"
  27. #endif
  28. #else
  29. #include <sys/param.h>
  30. #endif
  31. #include "ext/standard/head.h"
  32. #include "safe_mode.h"
  33. #include "php_string.h"
  34. #include "pack.h"
  35. #if HAVE_PWD_H
  36. #ifdef PHP_WIN32
  37. #include "win32/pwd.h"
  38. #elif defined(NETWARE)
  39. #include "netware/pwd.h"
  40. #else
  41. #include <pwd.h>
  42. #endif
  43. #endif
  44. #include "fsock.h"
  45. #if HAVE_NETINET_IN_H
  46. #include <netinet/in.h>
  47. #endif
  48.  
  49. #define INC_OUTPUTPOS(a,b) \
  50. if ((a) < 0 || ((INT_MAX - outputpos)/(b)) < (a)) { \
  51. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow in format string", code); \
  52. RETURN_FALSE; \
  53. } \
  54. outputpos += (a)*(b);
  55.  
  56. /* Whether machine is little endian */
  57. char machine_little_endian;
  58.  
  59. /* Mapping of byte from char (8bit) to long for machine endian */
  60. static int byte_map[1];
  61.  
  62. /* Mappings of bytes from int (machine dependant) to int for machine endian */
  63. static int int_map[sizeof(int)];
  64.  
  65. /* Mappings of bytes from shorts (16bit) for all endian environments */
  66. static int machine_endian_short_map[2];
  67. static int big_endian_short_map[2];
  68. static int little_endian_short_map[2];
  69.  
  70. /* Mappings of bytes from longs (32bit) for all endian environments */
  71. static int machine_endian_long_map[4];
  72. static int big_endian_long_map[4];
  73. static int little_endian_long_map[4];
  74.  
  75. /* {{{ php_pack
  76. */
  77. static void php_pack(zval **val, int size, int *map, char *output)
  78. {
  79. int i;
  80. char *v;
  81.  
  82. convert_to_long_ex(val);
  83. v = (char *) &Z_LVAL_PP(val);
  84.  
  85. for (i = 0; i < size; i++) {
  86. *output++ = v[map[i]];
  87. }
  88. }
  89. /* }}} */
  90.  
  91. /* pack() idea stolen from Perl (implemented formats behave the same as there)
  92. * Implemented formats are A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @.
  93. */
  94. /* {{{ proto string pack(string format, mixed arg1 [, mixed arg2 [, mixed ...]])
  95. Takes one or more arguments and packs them into a binary string according to the format argument */
  96. PHP_FUNCTION(pack)
  97. {
  98. zval ***argv;
  99. int argc, i;
  100. int currentarg;
  101. char *format;
  102. int formatlen;
  103. char *formatcodes;
  104. int *formatargs;
  105. int formatcount = 0;
  106. int outputpos = 0, outputsize = 0;
  107. char *output;
  108.  
  109. argc = ZEND_NUM_ARGS();
  110.  
  111. if (argc < 1) {
  112. WRONG_PARAM_COUNT;
  113. }
  114.  
  115. argv = safe_emalloc(sizeof(zval **), argc, 0);
  116.  
  117. if (zend_get_parameters_array_ex(argc, argv) == FAILURE) {
  118. efree(argv);
  119. WRONG_PARAM_COUNT;
  120. }
  121.  
  122. convert_to_string_ex(argv[0]);
  123. format = Z_STRVAL_PP(argv[0]);
  124. formatlen = Z_STRLEN_PP(argv[0]);
  125.  
  126. /* We have a maximum of <formatlen> format codes to deal with */
  127. formatcodes = safe_emalloc(formatlen, sizeof(*formatcodes), 0);
  128. formatargs = safe_emalloc(formatlen, sizeof(*formatargs), 0);
  129. currentarg = 1;
  130.  
  131. /* Preprocess format into formatcodes and formatargs */
  132. for (i = 0; i < formatlen; formatcount++) {
  133. char code = format[i++];
  134. int arg = 1;
  135.  
  136. /* Handle format arguments if any */
  137. if (i < formatlen) {
  138. char c = format[i];
  139.  
  140. if (c == '*') {
  141. arg = -1;
  142. i++;
  143. }
  144. else if (c >= '0' && c <= '9') {
  145. arg = atoi(&format[i]);
  146.  
  147. while (format[i] >= '0' && format[i] <= '9' && i < formatlen) {
  148. i++;
  149. }
  150. }
  151. }
  152.  
  153. /* Handle special arg '*' for all codes and check argv overflows */
  154. switch ((int) code) {
  155. /* Never uses any args */
  156. case 'x':
  157. case 'X':
  158. case '@':
  159. if (arg < 0) {
  160. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: '*' ignored", code);
  161. arg = 1;
  162. }
  163. break;
  164.  
  165. /* Always uses one arg */
  166. case 'a':
  167. case 'A':
  168. case 'h':
  169. case 'H':
  170. if (currentarg >= argc) {
  171. efree(argv);
  172. efree(formatcodes);
  173. efree(formatargs);
  174. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough arguments", code);
  175. RETURN_FALSE;
  176. }
  177.  
  178. if (arg < 0) {
  179. arg = Z_STRLEN_PP(argv[currentarg]);
  180. }
  181.  
  182. currentarg++;
  183. break;
  184.  
  185. /* Use as many args as specified */
  186. case 'c':
  187. case 'C':
  188. case 's':
  189. case 'S':
  190. case 'i':
  191. case 'I':
  192. case 'l':
  193. case 'L':
  194. case 'n':
  195. case 'N':
  196. case 'v':
  197. case 'V':
  198. case 'f':
  199. case 'd':
  200. if (arg < 0) {
  201. arg = argc - currentarg;
  202. }
  203.  
  204. currentarg += arg;
  205.  
  206. if (currentarg > argc) {
  207. efree(argv);
  208. efree(formatcodes);
  209. efree(formatargs);
  210. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: too few arguments", code);
  211. RETURN_FALSE;
  212. }
  213. break;
  214.  
  215. default:
  216. efree(argv);
  217. efree(formatcodes);
  218. efree(formatargs);
  219. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: unknown format code", code);
  220. RETURN_FALSE;
  221. }
  222.  
  223. formatcodes[formatcount] = code;
  224. formatargs[formatcount] = arg;
  225. }
  226.  
  227. if (currentarg < argc) {
  228. php_error_docref(NULL TSRMLS_CC, E_WARNING, "%d arguments unused", (argc - currentarg));
  229. }
  230.  
  231. /* Calculate output length and upper bound while processing*/
  232. for (i = 0; i < formatcount; i++) {
  233. int code = (int) formatcodes[i];
  234. int arg = formatargs[i];
  235.  
  236. switch ((int) code) {
  237. case 'h':
  238. case 'H':
  239. INC_OUTPUTPOS((arg + 1) / 2,1) /* 4 bit per arg */
  240. break;
  241.  
  242. case 'a':
  243. case 'A':
  244. case 'c':
  245. case 'C':
  246. case 'x':
  247. INC_OUTPUTPOS(arg,1) /* 8 bit per arg */
  248. break;
  249.  
  250. case 's':
  251. case 'S':
  252. case 'n':
  253. case 'v':
  254. INC_OUTPUTPOS(arg,2) /* 16 bit per arg */
  255. break;
  256.  
  257. case 'i':
  258. case 'I':
  259. INC_OUTPUTPOS(arg,sizeof(int))
  260. break;
  261.  
  262. case 'l':
  263. case 'L':
  264. case 'N':
  265. case 'V':
  266. INC_OUTPUTPOS(arg,4) /* 32 bit per arg */
  267. break;
  268.  
  269. case 'f':
  270. INC_OUTPUTPOS(arg,sizeof(float))
  271. break;
  272.  
  273. case 'd':
  274. INC_OUTPUTPOS(arg,sizeof(double))
  275. break;
  276.  
  277. case 'X':
  278. outputpos -= arg;
  279.  
  280. if (outputpos < 0) {
  281. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", code);
  282. outputpos = 0;
  283. }
  284. break;
  285.  
  286. case '@':
  287. outputpos = arg;
  288. break;
  289. }
  290.  
  291. if (outputsize < outputpos) {
  292. outputsize = outputpos;
  293. }
  294. }
  295.  
  296. output = emalloc(outputsize + 1);
  297. outputpos = 0;
  298. currentarg = 1;
  299.  
  300. /* Do actual packing */
  301. for (i = 0; i < formatcount; i++) {
  302. int code = (int) formatcodes[i];
  303. int arg = formatargs[i];
  304. zval **val;
  305.  
  306. switch ((int) code) {
  307. case 'a':
  308. case 'A':
  309. memset(&output[outputpos], (code == 'a') ? '\0' : ' ', arg);
  310. val = argv[currentarg++];
  311. convert_to_string_ex(val);
  312. memcpy(&output[outputpos], Z_STRVAL_PP(val),
  313. (Z_STRLEN_PP(val) < arg) ? Z_STRLEN_PP(val) : arg);
  314. outputpos += arg;
  315. break;
  316.  
  317. case 'h':
  318. case 'H': {
  319. int nibbleshift = (code == 'h') ? 0 : 4;
  320. int first = 1;
  321. char *v;
  322.  
  323. val = argv[currentarg++];
  324. convert_to_string_ex(val);
  325. v = Z_STRVAL_PP(val);
  326. outputpos--;
  327. if(arg > Z_STRLEN_PP(val)) {
  328. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough characters in string", code);
  329. arg = Z_STRLEN_PP(val);
  330. }
  331.  
  332. while (arg-- > 0) {
  333. char n = *v++;
  334.  
  335. if (n >= '0' && n <= '9') {
  336. n -= '0';
  337. } else if (n >= 'A' && n <= 'F') {
  338. n -= ('A' - 10);
  339. } else if (n >= 'a' && n <= 'f') {
  340. n -= ('a' - 10);
  341. } else {
  342. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: illegal hex digit %c", code, n);
  343. n = 0;
  344. }
  345.  
  346. if (first--) {
  347. output[++outputpos] = 0;
  348. } else {
  349. first = 1;
  350. }
  351.  
  352. output[outputpos] |= (n << nibbleshift);
  353. nibbleshift = (nibbleshift + 4) & 7;
  354. }
  355.  
  356. outputpos++;
  357. break;
  358. }
  359.  
  360. case 'c':
  361. case 'C':
  362. while (arg-- > 0) {
  363. php_pack(argv[currentarg++], 1, byte_map, &output[outputpos]);
  364. outputpos++;
  365. }
  366. break;
  367.  
  368. case 's':
  369. case 'S':
  370. case 'n':
  371. case 'v': {
  372. int *map = machine_endian_short_map;
  373.  
  374. if (code == 'n') {
  375. map = big_endian_short_map;
  376. } else if (code == 'v') {
  377. map = little_endian_short_map;
  378. }
  379.  
  380. while (arg-- > 0) {
  381. php_pack(argv[currentarg++], 2, map, &output[outputpos]);
  382. outputpos += 2;
  383. }
  384. break;
  385. }
  386.  
  387. case 'i':
  388. case 'I':
  389. while (arg-- > 0) {
  390. php_pack(argv[currentarg++], sizeof(int), int_map, &output[outputpos]);
  391. outputpos += sizeof(int);
  392. }
  393. break;
  394.  
  395. case 'l':
  396. case 'L':
  397. case 'N':
  398. case 'V': {
  399. int *map = machine_endian_long_map;
  400.  
  401. if (code == 'N') {
  402. map = big_endian_long_map;
  403. } else if (code == 'V') {
  404. map = little_endian_long_map;
  405. }
  406.  
  407. while (arg-- > 0) {
  408. php_pack(argv[currentarg++], 4, map, &output[outputpos]);
  409. outputpos += 4;
  410. }
  411. break;
  412. }
  413.  
  414. case 'f': {
  415. float v;
  416.  
  417. while (arg-- > 0) {
  418. val = argv[currentarg++];
  419. convert_to_double_ex(val);
  420. v = (float) Z_DVAL_PP(val);
  421. memcpy(&output[outputpos], &v, sizeof(v));
  422. outputpos += sizeof(v);
  423. }
  424. break;
  425. }
  426.  
  427. case 'd': {
  428. double v;
  429.  
  430. while (arg-- > 0) {
  431. val = argv[currentarg++];
  432. convert_to_double_ex(val);
  433. v = (double) Z_DVAL_PP(val);
  434. memcpy(&output[outputpos], &v, sizeof(v));
  435. outputpos += sizeof(v);
  436. }
  437. break;
  438. }
  439.  
  440. case 'x':
  441. memset(&output[outputpos], '\0', arg);
  442. outputpos += arg;
  443. break;
  444.  
  445. case 'X':
  446. outputpos -= arg;
  447.  
  448. if (outputpos < 0) {
  449. outputpos = 0;
  450. }
  451. break;
  452.  
  453. case '@':
  454. if (arg > outputpos) {
  455. memset(&output[outputpos], '\0', arg - outputpos);
  456. }
  457. outputpos = arg;
  458. break;
  459. }
  460. }
  461.  
  462. efree(argv);
  463. efree(formatcodes);
  464. efree(formatargs);
  465. output[outputpos] = '\0';
  466. RETVAL_STRINGL(output, outputpos, 1);
  467. efree(output);
  468. }
  469. /* }}} */
  470.  
  471. /* {{{ php_unpack
  472. */
  473. static long php_unpack(char *data, int size, int issigned, int *map)
  474. {
  475. long result;
  476. char *cresult = (char *) &result;
  477. int i;
  478.  
  479. result = issigned ? -1 : 0;
  480.  
  481. for (i = 0; i < size; i++) {
  482. cresult[map[i]] = *data++;
  483. }
  484.  
  485. return result;
  486. }
  487. /* }}} */
  488.  
  489. /* unpack() is based on Perl's unpack(), but is modified a bit from there.
  490. * Rather than depending on error-prone ordered lists or syntactically
  491. * unpleasant pass-by-reference, we return an object with named paramters
  492. * (like *_fetch_object()). Syntax is "f[repeat]name/...", where "f" is the
  493. * formatter char (like pack()), "[repeat]" is the optional repeater argument,
  494. * and "name" is the name of the variable to use.
  495. * Example: "c2chars/nints" will return an object with fields
  496. * chars1, chars2, and ints.
  497. * Numeric pack types will return numbers, a and A will return strings,
  498. * f and d will return doubles.
  499. * Implemented formats are A, a, h, H, c, C, s, S, i, I, l, L, n, N, f, d, x, X, @.
  500. */
  501. /* {{{ proto array unpack(string format, string input)
  502. Unpack binary string into named array elements according to format argument */
  503. PHP_FUNCTION(unpack)
  504. {
  505. zval **formatarg;
  506. zval **inputarg;
  507. char *format;
  508. char *input;
  509. int formatlen;
  510. int inputpos, inputlen;
  511. int i;
  512.  
  513. if (ZEND_NUM_ARGS() != 2 ||
  514. zend_get_parameters_ex(2, &formatarg, &inputarg) == FAILURE) {
  515. WRONG_PARAM_COUNT;
  516. }
  517.  
  518. convert_to_string_ex(formatarg);
  519. convert_to_string_ex(inputarg);
  520.  
  521. format = Z_STRVAL_PP(formatarg);
  522. formatlen = Z_STRLEN_PP(formatarg);
  523. input = Z_STRVAL_PP(inputarg);
  524. inputlen = Z_STRLEN_PP(inputarg);
  525. inputpos = 0;
  526.  
  527. array_init(return_value);
  528.  
  529. while (formatlen-- > 0) {
  530. char type = *(format++);
  531. char c;
  532. int arg = 1;
  533. char *name;
  534. int namelen;
  535. int size=0;
  536.  
  537. /* Handle format arguments if any */
  538. if (formatlen > 0) {
  539. c = *format;
  540.  
  541. if (c >= '0' && c <= '9') {
  542. arg = atoi(format);
  543.  
  544. while (formatlen > 0 && *format >= '0' && *format <= '9') {
  545. format++;
  546. formatlen--;
  547. }
  548. } else if (c == '*') {
  549. arg = -1;
  550. format++;
  551. formatlen--;
  552. }
  553. }
  554.  
  555. /* Get of new value in array */
  556. name = format;
  557.  
  558. while (formatlen > 0 && *format != '/') {
  559. formatlen--;
  560. format++;
  561. }
  562.  
  563. namelen = format - name;
  564.  
  565. if (namelen > 200)
  566. namelen = 200;
  567.  
  568. switch ((int) type) {
  569. /* Never use any input */
  570. case 'X':
  571. size = -1;
  572. break;
  573.  
  574. case '@':
  575. size = 0;
  576. break;
  577.  
  578. case 'a':
  579. case 'A':
  580. size = arg;
  581. arg = 1;
  582. break;
  583.  
  584. case 'h':
  585. case 'H':
  586. size = (arg > 0) ? arg / 2 : arg;
  587. arg = 1;
  588. break;
  589.  
  590. /* Use 1 byte of input */
  591. case 'c':
  592. case 'C':
  593. case 'x':
  594. size = 1;
  595. break;
  596.  
  597. /* Use 2 bytes of input */
  598. case 's':
  599. case 'S':
  600. case 'n':
  601. case 'v':
  602. size = 2;
  603. break;
  604.  
  605. /* Use sizeof(int) bytes of input */
  606. case 'i':
  607. case 'I':
  608. size = sizeof(int);
  609. break;
  610.  
  611. /* Use 4 bytes of input */
  612. case 'l':
  613. case 'L':
  614. case 'N':
  615. case 'V':
  616. size = 4;
  617. break;
  618.  
  619. /* Use sizeof(float) bytes of input */
  620. case 'f':
  621. size = sizeof(float);
  622. break;
  623.  
  624. /* Use sizeof(double) bytes of input */
  625. case 'd':
  626. size = sizeof(double);
  627. break;
  628. }
  629.  
  630. /* Do actual unpacking */
  631. for (i = 0; i != arg; i++ ) {
  632. /* Space for name + number, safe as namelen is ensured <= 200 */
  633. char n[256];
  634.  
  635. if (arg != 1 || namelen == 0) {
  636. /* Need to add element number to name */
  637. sprintf(n, "%.*s%d", namelen, name, i + 1);
  638. } else {
  639. /* Truncate name to next format code or end of string */
  640. sprintf(n, "%.*s", namelen, name);
  641. }
  642.  
  643. if (size != 0 && size != -1 && INT_MAX - size + 1 < inputpos) {
  644. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: integer overflow", type);
  645. inputpos = 0;
  646. }
  647.  
  648. if ((inputpos + size) <= inputlen) {
  649. switch ((int) type) {
  650. case 'a':
  651. case 'A': {
  652. char pad = (type == 'a') ? '\0' : ' ';
  653. int len = inputlen - inputpos; /* Remaining string */
  654.  
  655. /* If size was given take minimum of len and size */
  656. if ((size >= 0) && (len > size)) {
  657. len = size;
  658. }
  659.  
  660. size = len;
  661.  
  662. /* Remove padding chars from unpacked data */
  663. while (--len >= 0) {
  664. if (input[inputpos + len] != pad)
  665. break;
  666. }
  667.  
  668. add_assoc_stringl(return_value, n, &input[inputpos], len + 1, 1);
  669. break;
  670. }
  671.  
  672. case 'h':
  673. case 'H': {
  674. int len = (inputlen - inputpos) * 2; /* Remaining */
  675. int nibbleshift = (type == 'h') ? 0 : 4;
  676. int first = 1;
  677. char *buf;
  678. int ipos, opos;
  679.  
  680. /* If size was given take minimum of len and size */
  681. if (size >= 0 && len > (size * 2)) {
  682. len = size * 2;
  683. }
  684.  
  685. buf = emalloc(len + 1);
  686.  
  687. for (ipos = opos = 0; opos < len; opos++) {
  688. char c = (input[inputpos + ipos] >> nibbleshift) & 0xf;
  689.  
  690. if (c < 10) {
  691. c += '0';
  692. } else {
  693. c += 'a' - 10;
  694. }
  695.  
  696. buf[opos] = c;
  697. nibbleshift = (nibbleshift + 4) & 7;
  698.  
  699. if (first-- == 0) {
  700. ipos++;
  701. first = 1;
  702. }
  703. }
  704.  
  705. buf[len] = '\0';
  706. add_assoc_stringl(return_value, n, buf, len, 1);
  707. efree(buf);
  708. break;
  709. }
  710.  
  711. case 'c':
  712. case 'C': {
  713. int issigned = (type == 'c') ? (input[inputpos] & 0x80) : 0;
  714. long v = php_unpack(&input[inputpos], 1, issigned, byte_map);
  715. add_assoc_long(return_value, n, v);
  716. break;
  717. }
  718.  
  719. case 's':
  720. case 'S':
  721. case 'n':
  722. case 'v': {
  723. long v;
  724. int issigned = 0;
  725. int *map = machine_endian_short_map;
  726.  
  727. if (type == 's') {
  728. issigned = input[inputpos + (machine_little_endian ? 1 : 0)] & 0x80;
  729. } else if (type == 'n') {
  730. map = big_endian_short_map;
  731. } else if (type == 'v') {
  732. map = little_endian_short_map;
  733. }
  734.  
  735. v = php_unpack(&input[inputpos], 2, issigned, map);
  736. add_assoc_long(return_value, n, v);
  737. break;
  738. }
  739.  
  740. case 'i':
  741. case 'I': {
  742. long v;
  743. int issigned = 0;
  744.  
  745. if (type == 'i') {
  746. issigned = input[inputpos + (machine_little_endian ? (sizeof(int) - 1) : 0)] & 0x80;
  747. }
  748.  
  749. v = php_unpack(&input[inputpos], sizeof(int), issigned, int_map);
  750. add_assoc_long(return_value, n, v);
  751. break;
  752. }
  753.  
  754. case 'l':
  755. case 'L':
  756. case 'N':
  757. case 'V': {
  758. int issigned = 0;
  759. int *map = machine_endian_long_map;
  760. long v;
  761.  
  762. if (type == 'l') {
  763. issigned = input[inputpos + (machine_little_endian ? 3 : 0)] & 0x80;
  764. } else if (type == 'N') {
  765. map = big_endian_long_map;
  766. } else if (type == 'V') {
  767. map = little_endian_long_map;
  768. }
  769.  
  770. v = php_unpack(&input[inputpos], 4, issigned, map);
  771. add_assoc_long(return_value, n, v);
  772. break;
  773. }
  774.  
  775. case 'f': {
  776. float v;
  777.  
  778. memcpy(&v, &input[inputpos], sizeof(float));
  779. add_assoc_double(return_value, n, (double)v);
  780. break;
  781. }
  782.  
  783. case 'd': {
  784. double v;
  785.  
  786. memcpy(&v, &input[inputpos], sizeof(double));
  787. add_assoc_double(return_value, n, v);
  788. break;
  789. }
  790.  
  791. case 'x':
  792. /* Do nothing with input, just skip it */
  793. break;
  794.  
  795. case 'X':
  796. if (inputpos < size) {
  797. inputpos = -size;
  798. i = arg - 1; /* Break out of for loop */
  799.  
  800. if (arg >= 0) {
  801. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
  802. }
  803. }
  804. break;
  805.  
  806. case '@':
  807. if (arg <= inputlen) {
  808. inputpos = arg;
  809. } else {
  810. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
  811. }
  812.  
  813. i = arg - 1; /* Done, break out of for loop */
  814. break;
  815. }
  816.  
  817. inputpos += size;
  818. if (inputpos < 0) {
  819. if (size != -1) { /* only print warning if not working with * */
  820. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: outside of string", type);
  821. }
  822. inputpos = 0;
  823. }
  824. } else if (arg < 0) {
  825. /* Reached end of input for '*' repeater */
  826. break;
  827. } else {
  828. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos);
  829. zval_dtor(return_value);
  830. RETURN_FALSE;
  831. }
  832. }
  833.  
  834. formatlen--; /* Skip '/' separator, does no harm if inputlen == 0 */
  835. format++;
  836. }
  837. }
  838. /* }}} */
  839.  
  840. /* {{{ PHP_MINIT_FUNCTION
  841. */
  842. PHP_MINIT_FUNCTION(pack)
  843. {
  844. int machine_endian_check = 1;
  845. int i;
  846.  
  847. machine_little_endian = ((char *)&machine_endian_check)[0];
  848.  
  849. if (machine_little_endian) {
  850. /* Where to get lo to hi bytes from */
  851. byte_map[0] = 0;
  852.  
  853. for (i = 0; i < sizeof(int); i++) {
  854. int_map[i] = i;
  855. }
  856.  
  857. machine_endian_short_map[0] = 0;
  858. machine_endian_short_map[1] = 1;
  859. big_endian_short_map[0] = 1;
  860. big_endian_short_map[1] = 0;
  861. little_endian_short_map[0] = 0;
  862. little_endian_short_map[1] = 1;
  863.  
  864. machine_endian_long_map[0] = 0;
  865. machine_endian_long_map[1] = 1;
  866. machine_endian_long_map[2] = 2;
  867. machine_endian_long_map[3] = 3;
  868. big_endian_long_map[0] = 3;
  869. big_endian_long_map[1] = 2;
  870. big_endian_long_map[2] = 1;
  871. big_endian_long_map[3] = 0;
  872. little_endian_long_map[0] = 0;
  873. little_endian_long_map[1] = 1;
  874. little_endian_long_map[2] = 2;
  875. little_endian_long_map[3] = 3;
  876. }
  877. else {
  878. zval val;
  879. int size = sizeof(Z_LVAL(val));
  880. Z_LVAL(val)=0; /*silence a warning*/
  881.  
  882. /* Where to get hi to lo bytes from */
  883. byte_map[0] = size - 1;
  884.  
  885. for (i = 0; i < sizeof(int); i++) {
  886. int_map[i] = size - (sizeof(int) - i);
  887. }
  888.  
  889. machine_endian_short_map[0] = size - 2;
  890. machine_endian_short_map[1] = size - 1;
  891. big_endian_short_map[0] = size - 2;
  892. big_endian_short_map[1] = size - 1;
  893. little_endian_short_map[0] = size - 1;
  894. little_endian_short_map[1] = size - 2;
  895.  
  896. machine_endian_long_map[0] = size - 4;
  897. machine_endian_long_map[1] = size - 3;
  898. machine_endian_long_map[2] = size - 2;
  899. machine_endian_long_map[3] = size - 1;
  900. big_endian_long_map[0] = size - 4;
  901. big_endian_long_map[1] = size - 3;
  902. big_endian_long_map[2] = size - 2;
  903. big_endian_long_map[3] = size - 1;
  904. little_endian_long_map[0] = size - 1;
  905. little_endian_long_map[1] = size - 2;
  906. little_endian_long_map[2] = size - 3;
  907. little_endian_long_map[3] = size - 4;
  908. }
  909.  
  910. return SUCCESS;
  911. }
  912. /* }}} */
  913.  
  914. /*
  915. * Local variables:
  916. * tab-width: 4
  917. * c-basic-offset: 4
  918. * End:
  919. * vim600: noet sw=4 ts=4 fdm=marker
  920. * vim<600: noet sw=4 ts=4
  921. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement