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