Annotation of embedaddon/php/ext/interbase/ibase_blobs.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Ard Biesheuvel <a.k.biesheuvel@its.tudelft.nl> |
16: +----------------------------------------------------------------------+
17: */
18:
19: /* $Id: ibase_blobs.c 321634 2012-01-01 13:15:04Z felipe $ */
20:
21: #ifdef HAVE_CONFIG_H
22: #include "config.h"
23: #endif
24:
25: #include "php.h"
26:
27: #if HAVE_IBASE
28:
29: #include "php_interbase.h"
30: #include "php_ibase_includes.h"
31:
32: #define BLOB_CLOSE 1
33: #define BLOB_CANCEL 2
34:
35: static int le_blob;
36:
37: static void _php_ibase_free_blob(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
38: {
39: ibase_blob *ib_blob = (ibase_blob *)rsrc->ptr;
40:
41: if (ib_blob->bl_handle != NULL) { /* blob open*/
42: if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) {
43: _php_ibase_module_error("You can lose data. Close any blob after reading from or "
44: "writing to it. Use ibase_blob_close() before calling ibase_close()" TSRMLS_CC);
45: }
46: }
47: efree(ib_blob);
48: }
49: /* }}} */
50:
51: void php_ibase_blobs_minit(INIT_FUNC_ARGS) /* {{{ */
52: {
53: le_blob = zend_register_list_destructors_ex(_php_ibase_free_blob, NULL,
54: "interbase blob", module_number);
55: }
56: /* }}} */
57:
58: int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd) /* {{{ */
59: {
60: /* shortcut for most common case */
61: if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) {
62: return sscanf(id, BLOB_ID_MASK, (ISC_UINT64 *) qd);
63: } else {
64: ISC_UINT64 res;
65: if (sscanf(id, BLOB_ID_MASK, &res)) {
66: qd->gds_quad_high = (ISC_LONG) (res >> 0x20);
67: qd->gds_quad_low = (ISC_LONG) (res & 0xFFFFFFFF);
68: return 1;
69: }
70: return 0;
71: }
72: }
73: /* }}} */
74:
75: char *_php_ibase_quad_to_string(ISC_QUAD const qd) /* {{{ */
76: {
77: char *result;
78:
79: /* shortcut for most common case */
80: if (sizeof(ISC_QUAD) == sizeof(ISC_UINT64)) {
81: spprintf(&result, BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, *(ISC_UINT64*)(void *) &qd);
82: } else {
83: ISC_UINT64 res = ((ISC_UINT64) qd.gds_quad_high << 0x20) | qd.gds_quad_low;
84: spprintf(&result, BLOB_ID_LEN+1, "0x%0*" LL_MASK "x", 16, res);
85: }
86: return result;
87: }
88: /* }}} */
89:
90: typedef struct { /* {{{ */
91: ISC_LONG max_segment; /* Length of longest segment */
92: ISC_LONG num_segments; /* Total number of segments */
93: ISC_LONG total_length; /* Total length of blob */
94: int bl_stream; /* blob is stream ? */
95: /* }}} */
96: } IBASE_BLOBINFO;
97:
98: int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long max_len TSRMLS_DC) /* {{{ */
99: {
100: if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/
101:
102: ISC_STATUS stat;
103: char *bl_data;
104: unsigned long cur_len;
105: unsigned short seg_len;
106:
107: bl_data = safe_emalloc(1, max_len, 1);
108:
109: for (cur_len = stat = 0; (stat == 0 || stat == isc_segment) && cur_len < max_len; cur_len += seg_len) {
110:
111: unsigned short chunk_size = (max_len-cur_len) > USHRT_MAX ? USHRT_MAX
112: : (unsigned short)(max_len-cur_len);
113:
114: stat = isc_get_segment(IB_STATUS, &ib_blob->bl_handle, &seg_len, chunk_size, &bl_data[cur_len]);
115: }
116:
117: bl_data[cur_len] = '\0';
118: if (IB_STATUS[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
119: efree(bl_data);
120: _php_ibase_error(TSRMLS_C);
121: return FAILURE;
122: }
123: RETVAL_STRINGL(bl_data, cur_len, 0);
124: } else { /* null blob */
125: RETVAL_STRING("", 1); /* empty string */
126: }
127: return SUCCESS;
128: }
129: /* }}} */
130:
131: int _php_ibase_blob_add(zval **string_arg, ibase_blob *ib_blob TSRMLS_DC) /* {{{ */
132: {
133: unsigned long put_cnt = 0, rem_cnt;
134: unsigned short chunk_size;
135:
136: convert_to_string_ex(string_arg);
137:
138: for (rem_cnt = Z_STRLEN_PP(string_arg); rem_cnt > 0; rem_cnt -= chunk_size) {
139:
140: chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
141:
142: if (isc_put_segment(IB_STATUS, &ib_blob->bl_handle, chunk_size, &Z_STRVAL_PP(string_arg)[put_cnt] )) {
143: _php_ibase_error(TSRMLS_C);
144: return FAILURE;
145: }
146: put_cnt += chunk_size;
147: }
148: return SUCCESS;
149: }
150: /* }}} */
151:
152: static int _php_ibase_blob_info(isc_blob_handle bl_handle, IBASE_BLOBINFO *bl_info TSRMLS_DC) /* {{{ */
153: {
154: static char bl_items[] = {
155: isc_info_blob_num_segments,
156: isc_info_blob_max_segment,
157: isc_info_blob_total_length,
158: isc_info_blob_type
159: };
160:
161: char bl_inf[sizeof(long)*8], *p;
162:
163: bl_info->max_segment = 0;
164: bl_info->num_segments = 0;
165: bl_info->total_length = 0;
166: bl_info->bl_stream = 0;
167:
168: if (isc_blob_info(IB_STATUS, &bl_handle, sizeof(bl_items), bl_items, sizeof(bl_inf), bl_inf)) {
169: _php_ibase_error(TSRMLS_C);
170: return FAILURE;
171: }
172:
173: for (p = bl_inf; *p != isc_info_end && p < bl_inf + sizeof(bl_inf);) {
174: unsigned short item_len;
175: int item = *p++;
176:
177: item_len = (short) isc_vax_integer(p, 2);
178: p += 2;
179: switch (item) {
180: case isc_info_blob_num_segments:
181: bl_info->num_segments = isc_vax_integer(p, item_len);
182: break;
183: case isc_info_blob_max_segment:
184: bl_info->max_segment = isc_vax_integer(p, item_len);
185: break;
186: case isc_info_blob_total_length:
187: bl_info->total_length = isc_vax_integer(p, item_len);
188: break;
189: case isc_info_blob_type:
190: bl_info->bl_stream = isc_vax_integer(p, item_len);
191: break;
192: case isc_info_end:
193: break;
194: case isc_info_truncated:
195: case isc_info_error: /* hmm. don't think so...*/
196: _php_ibase_module_error("PHP module internal error" TSRMLS_CC);
197: return FAILURE;
198: } /* switch */
199: p += item_len;
200: } /* for */
201: return SUCCESS;
202: }
203: /* }}} */
204:
205: /* {{{ proto resource ibase_blob_create([resource link_identifier])
206: Create blob for adding data */
207: PHP_FUNCTION(ibase_blob_create)
208: {
209: zval *link = NULL;
210: ibase_db_link *ib_link;
211: ibase_trans *trans = NULL;
212: ibase_blob *ib_blob;
213:
214: RESET_ERRMSG;
215:
216: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &link)) {
217: RETURN_FALSE;
218: }
219:
220: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
221:
222: ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob));
223: ib_blob->bl_handle = NULL;
224: ib_blob->type = BLOB_INPUT;
225:
226: if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle, &ib_blob->bl_qd)) {
227: _php_ibase_error(TSRMLS_C);
228: efree(ib_blob);
229: RETURN_FALSE;
230: }
231:
232: ZEND_REGISTER_RESOURCE(return_value, ib_blob, le_blob);
233: }
234: /* }}} */
235:
236: /* {{{ proto resource ibase_blob_open([ resource link_identifier, ] string blob_id)
237: Open blob for retrieving data parts */
238: PHP_FUNCTION(ibase_blob_open)
239: {
240: char *blob_id;
241: int blob_id_len;
242: zval *link = NULL;
243: ibase_db_link *ib_link;
244: ibase_trans *trans = NULL;
245: ibase_blob *ib_blob;
246:
247: RESET_ERRMSG;
248:
249: switch (ZEND_NUM_ARGS()) {
250: default:
251: WRONG_PARAM_COUNT;
252: case 1:
253: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) {
254: RETURN_FALSE;
255: }
256: break;
257: case 2:
258: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) {
259: RETURN_FALSE;
260: }
261: break;
262: }
263:
264: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
265:
266: ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob));
267: ib_blob->bl_handle = NULL;
268: ib_blob->type = BLOB_OUTPUT;
269:
270: do {
271: if (! _php_ibase_string_to_quad(blob_id, &ib_blob->bl_qd)) {
272: _php_ibase_module_error("String is not a BLOB ID" TSRMLS_CC);
273: break;
274: }
275:
276: if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle,
277: &ib_blob->bl_qd)) {
278: _php_ibase_error(TSRMLS_C);
279: break;
280: }
281:
282: ZEND_REGISTER_RESOURCE(return_value, ib_blob, le_blob);
283: return;
284:
285: } while (0);
286:
287: efree(ib_blob);
288: RETURN_FALSE;
289: }
290: /* }}} */
291:
292: /* {{{ proto bool ibase_blob_add(resource blob_handle, string data)
293: Add data into created blob */
294: PHP_FUNCTION(ibase_blob_add)
295: {
296: zval **blob_arg, **string_arg;
297: ibase_blob *ib_blob;
298:
299: RESET_ERRMSG;
300:
301: if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &blob_arg, &string_arg) == FAILURE) {
302: WRONG_PARAM_COUNT;
303: }
304:
305: ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob);
306:
307: if (ib_blob->type != BLOB_INPUT) {
308: _php_ibase_module_error("BLOB is not open for input" TSRMLS_CC);
309: RETURN_FALSE;
310: }
311:
312: if (_php_ibase_blob_add(string_arg, ib_blob TSRMLS_CC) != SUCCESS) {
313: RETURN_FALSE;
314: }
315: }
316: /* }}} */
317:
318: /* {{{ proto string ibase_blob_get(resource blob_handle, int len)
319: Get len bytes data from open blob */
320: PHP_FUNCTION(ibase_blob_get)
321: {
322: zval **blob_arg, **len_arg;
323: ibase_blob *ib_blob;
324:
325: RESET_ERRMSG;
326:
327: if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &blob_arg, &len_arg) == FAILURE) {
328: WRONG_PARAM_COUNT;
329: }
330:
331: ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob);
332:
333: if (ib_blob->type != BLOB_OUTPUT) {
334: _php_ibase_module_error("BLOB is not open for output" TSRMLS_CC);
335: RETURN_FALSE;
336: }
337:
338: convert_to_long_ex(len_arg);
339:
340: if (_php_ibase_blob_get(return_value, ib_blob, Z_LVAL_PP(len_arg) TSRMLS_CC) != SUCCESS) {
341: RETURN_FALSE;
342: }
343: }
344: /* }}} */
345:
346: static void _php_ibase_blob_end(INTERNAL_FUNCTION_PARAMETERS, int bl_end) /* {{{ */
347: {
348: zval **blob_arg;
349: ibase_blob *ib_blob;
350:
351: RESET_ERRMSG;
352:
353: if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &blob_arg) == FAILURE) {
354: WRONG_PARAM_COUNT;
355: }
356:
357: ZEND_FETCH_RESOURCE(ib_blob, ibase_blob *, blob_arg, -1, "Interbase blob", le_blob);
358:
359: if (bl_end == BLOB_CLOSE) { /* return id here */
360:
361: if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/
362: if (isc_close_blob(IB_STATUS, &ib_blob->bl_handle)) {
363: _php_ibase_error(TSRMLS_C);
364: RETURN_FALSE;
365: }
366: }
367: ib_blob->bl_handle = NULL;
368:
369: RETVAL_STRINGL(_php_ibase_quad_to_string(ib_blob->bl_qd), BLOB_ID_LEN, 0);
370: } else { /* discard created blob */
371: if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) {
372: _php_ibase_error(TSRMLS_C);
373: RETURN_FALSE;
374: }
375: ib_blob->bl_handle = NULL;
376: RETVAL_TRUE;
377: }
378: zend_list_delete(Z_LVAL_PP(blob_arg));
379: }
380: /* }}} */
381:
382: /* {{{ proto string ibase_blob_close(resource blob_handle)
383: Close blob */
384: PHP_FUNCTION(ibase_blob_close)
385: {
386: _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CLOSE);
387: }
388: /* }}} */
389:
390: /* {{{ proto bool ibase_blob_cancel(resource blob_handle)
391: Cancel creating blob */
392: PHP_FUNCTION(ibase_blob_cancel)
393: {
394: _php_ibase_blob_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, BLOB_CANCEL);
395: }
396: /* }}} */
397:
398: /* {{{ proto array ibase_blob_info([ resource link_identifier, ] string blob_id)
399: Return blob length and other useful info */
400: PHP_FUNCTION(ibase_blob_info)
401: {
402: char *blob_id;
403: int blob_id_len;
404: zval *link = NULL;
405: ibase_db_link *ib_link;
406: ibase_trans *trans = NULL;
407: ibase_blob ib_blob = { NULL, BLOB_INPUT };
408: IBASE_BLOBINFO bl_info;
409:
410: RESET_ERRMSG;
411:
412: switch (ZEND_NUM_ARGS()) {
413: default:
414: WRONG_PARAM_COUNT;
415: case 1:
416: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) {
417: RETURN_FALSE;
418: }
419: break;
420: case 2:
421: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) {
422: RETURN_FALSE;
423: }
424: break;
425: }
426:
427: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
428:
429: if (! _php_ibase_string_to_quad(blob_id, &ib_blob.bl_qd)) {
430: _php_ibase_module_error("Unrecognized BLOB ID" TSRMLS_CC);
431: RETURN_FALSE;
432: }
433:
434: if (ib_blob.bl_qd.gds_quad_high || ib_blob.bl_qd.gds_quad_low) { /* not null ? */
435: if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle,
436: &ib_blob.bl_qd)) {
437: _php_ibase_error(TSRMLS_C);
438: RETURN_FALSE;
439: }
440:
441: if (_php_ibase_blob_info(ib_blob.bl_handle, &bl_info TSRMLS_CC)) {
442: RETURN_FALSE;
443: }
444: if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
445: _php_ibase_error(TSRMLS_C);
446: RETURN_FALSE;
447: }
448: } else { /* null blob, all values to zero */
449: bl_info.max_segment = 0;
450: bl_info.num_segments = 0;
451: bl_info.total_length = 0;
452: bl_info.bl_stream = 0;
453: }
454:
455: array_init(return_value);
456:
457: add_index_long(return_value, 0, bl_info.total_length);
458: add_assoc_long(return_value, "length", bl_info.total_length);
459:
460: add_index_long(return_value, 1, bl_info.num_segments);
461: add_assoc_long(return_value, "numseg", bl_info.num_segments);
462:
463: add_index_long(return_value, 2, bl_info.max_segment);
464: add_assoc_long(return_value, "maxseg", bl_info.max_segment);
465:
466: add_index_bool(return_value, 3, bl_info.bl_stream);
467: add_assoc_bool(return_value, "stream", bl_info.bl_stream);
468:
469: add_index_bool(return_value, 4, (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low));
470: add_assoc_bool(return_value, "isnull", (!ib_blob.bl_qd.gds_quad_high && !ib_blob.bl_qd.gds_quad_low));
471: }
472: /* }}} */
473:
474: /* {{{ proto bool ibase_blob_echo([ resource link_identifier, ] string blob_id)
475: Output blob contents to browser */
476: PHP_FUNCTION(ibase_blob_echo)
477: {
478: char *blob_id;
479: int blob_id_len;
480: zval *link = NULL;
481: ibase_db_link *ib_link;
482: ibase_trans *trans = NULL;
483: ibase_blob ib_blob_id = { NULL, BLOB_OUTPUT };
484: char bl_data[IBASE_BLOB_SEG];
485: unsigned short seg_len;
486:
487: RESET_ERRMSG;
488:
489: switch (ZEND_NUM_ARGS()) {
490: default:
491: WRONG_PARAM_COUNT;
492: case 1:
493: if (FAILURE == zend_parse_parameters(1 TSRMLS_CC, "s", &blob_id, &blob_id_len)) {
494: RETURN_FALSE;
495: }
496: break;
497: case 2:
498: if (FAILURE == zend_parse_parameters(2 TSRMLS_CC, "rs", &link, &blob_id, &blob_id_len)) {
499: RETURN_FALSE;
500: }
501: break;
502: }
503:
504: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
505:
506: if (! _php_ibase_string_to_quad(blob_id, &ib_blob_id.bl_qd)) {
507: _php_ibase_module_error("Unrecognized BLOB ID" TSRMLS_CC);
508: RETURN_FALSE;
509: }
510:
511: do {
512: if (isc_open_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob_id.bl_handle,
513: &ib_blob_id.bl_qd)) {
514: break;
515: }
516:
517: while (!isc_get_segment(IB_STATUS, &ib_blob_id.bl_handle, &seg_len, sizeof(bl_data), bl_data)
518: || IB_STATUS[1] == isc_segment) {
519: PHPWRITE(bl_data, seg_len);
520: }
521:
522: if (IB_STATUS[0] && (IB_STATUS[1] != isc_segstr_eof)) {
523: break;
524: }
525:
526: if (isc_close_blob(IB_STATUS, &ib_blob_id.bl_handle)) {
527: break;
528: }
529: RETURN_TRUE;
530: } while (0);
531:
532: _php_ibase_error(TSRMLS_C);
533: RETURN_FALSE;
534: }
535: /* }}} */
536:
537: /* {{{ proto string ibase_blob_import([ resource link_identifier, ] resource file)
538: Create blob, copy file in it, and close it */
539: PHP_FUNCTION(ibase_blob_import)
540: {
541: zval *link = NULL, *file;
542: int size;
543: unsigned short b;
544: ibase_blob ib_blob = { NULL, 0 };
545: ibase_db_link *ib_link;
546: ibase_trans *trans = NULL;
547: char bl_data[IBASE_BLOB_SEG];
548: php_stream *stream;
549:
550: RESET_ERRMSG;
551:
552: if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|r",
553: (ZEND_NUM_ARGS()-1) ? &link : &file, &file)) {
554: RETURN_FALSE;
555: }
556:
557: PHP_IBASE_LINK_TRANS(link, ib_link, trans);
558:
559: php_stream_from_zval(stream, &file);
560:
561: do {
562: if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob.bl_handle,
563: &ib_blob.bl_qd)) {
564: break;
565: }
566:
567: for (size = 0; (b = php_stream_read(stream, bl_data, sizeof(bl_data))); size += b) {
568: if (isc_put_segment(IB_STATUS, &ib_blob.bl_handle, b, bl_data)) {
569: break;
570: }
571: }
572:
573: if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
574: break;
575: }
576: RETURN_STRINGL( _php_ibase_quad_to_string(ib_blob.bl_qd), BLOB_ID_LEN, 0);
577: } while (0);
578:
579: _php_ibase_error(TSRMLS_C);
580: RETURN_FALSE;
581: }
582: /* }}} */
583:
584: #endif /* HAVE_IBASE */
585:
586: /*
587: * Local variables:
588: * tab-width: 4
589: * c-basic-offset: 4
590: * End:
591: * vim600: sw=4 ts=4 fdm=marker
592: * vim<600: sw=4 ts=4
593: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>