Annotation of embedaddon/php/ext/oci8/oci8_lob.c, revision 1.1.1.2

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: Stig Sæther Bakken <ssb@php.net>                            |
                     16:    |          Thies C. Arntzen <thies@thieso.net>                         |
                     17:    |                                                                      |
                     18:    | Collection support by Andy Sautins <asautins@veripost.net>           |
                     19:    | Temporary LOB support by David Benson <dbenson@mancala.com>          |
                     20:    | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at>        |
                     21:    |                                                                      |
                     22:    | Redesigned by: Antony Dovgal <antony@zend.com>                       |
                     23:    |                Andi Gutmans <andi@zend.com>                          |
                     24:    |                Wez Furlong <wez@omniti.com>                          |
                     25:    +----------------------------------------------------------------------+
                     26: */
                     27: 
1.1.1.2 ! misho      28: /* $Id$ */
1.1       misho      29: 
                     30: 
                     31: 
                     32: #ifdef HAVE_CONFIG_H
                     33: #include "config.h"
                     34: #endif
                     35: 
                     36: #include "php.h"
                     37: #include "ext/standard/info.h"
                     38: #include "php_ini.h"
                     39: 
                     40: #if HAVE_OCI8
                     41: 
                     42: #include "php_oci8.h"
                     43: #include "php_oci8_int.h"
                     44: 
                     45: /* for import/export functions */
                     46: #include <fcntl.h>
                     47: 
                     48: #ifndef O_BINARY
                     49: #define O_BINARY 0
                     50: #endif
                     51: 
                     52: /* {{{ php_oci_lob_create()
                     53:  Create LOB descriptor and allocate all the resources needed */
                     54: php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC)
                     55: {
                     56:        php_oci_descriptor *descriptor;
                     57: 
                     58:        switch (type) {
                     59:                case OCI_DTYPE_FILE:
                     60:                case OCI_DTYPE_LOB:
                     61:                case OCI_DTYPE_ROWID:
                     62:                        /* these three are allowed */
                     63:                        break;
                     64:                default:
                     65:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %ld", type);
                     66:                        return NULL;
                     67:                        break;
                     68:        }
                     69: 
                     70:        descriptor = ecalloc(1, sizeof(php_oci_descriptor));
                     71:        descriptor->type = type;
                     72:        descriptor->connection = connection;
                     73:        zend_list_addref(descriptor->connection->rsrc_id);
                     74: 
                     75:        PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
                     76: 
                     77:        if (OCI_G(errcode) != OCI_SUCCESS) {
                     78:                OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
                     79:                PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode));
                     80:                efree(descriptor);
                     81:                return NULL;
                     82:        }
                     83: 
                     84:        PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor);
                     85:        
                     86:        descriptor->lob_current_position = 0;
                     87:        descriptor->lob_size = -1;                              /* we should set it to -1 to know, that it's just not initialized */
                     88:        descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED;                            /* buffering is off by default */
                     89:        descriptor->charset_form = SQLCS_IMPLICIT;      /* default value */
                     90:        descriptor->charset_id = connection->charset;
                     91:        descriptor->is_open = 0;
                     92: 
                     93:        if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
                     94:                /* add Lobs & Files to hash. we'll flush them at the end */
                     95:                if (!connection->descriptors) {
                     96:                        ALLOC_HASHTABLE(connection->descriptors);
                     97:                        zend_hash_init(connection->descriptors, 0, NULL, php_oci_descriptor_flush_hash_dtor, 0);
                     98:                        connection->descriptor_count = 0;
                     99:                }
                    100:                
                    101:                descriptor->index = (connection->descriptor_count)++;
                    102:                if (connection->descriptor_count == LONG_MAX) {
                    103:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal descriptor counter has reached limit");
                    104:                        php_oci_connection_descriptors_free(connection TSRMLS_CC);
                    105:                        return NULL;
                    106:                }
                    107: 
                    108:                zend_hash_index_update(connection->descriptors,descriptor->index,&descriptor,sizeof(php_oci_descriptor *),NULL);
                    109:        }
                    110:        return descriptor;
                    111: 
                    112: } /* }}} */
                    113: 
                    114: /* {{{ php_oci_lob_get_length()
                    115:  Get length of the LOB. The length is cached so we don't need to ask Oracle every time */
                    116: int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC)
                    117: {
                    118:        php_oci_connection *connection = descriptor->connection;
                    119: 
                    120:        *length = 0;
                    121:        
                    122:        if (descriptor->lob_size >= 0) {
                    123:                *length = descriptor->lob_size;
                    124:                return 0;
                    125:        } else {
                    126:                if (descriptor->type == OCI_DTYPE_FILE) {
                    127:                        PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
                    128:                        if (connection->errcode != OCI_SUCCESS) {
                    129:                                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    130:                                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    131:                                return 1;
                    132:                        }
                    133:                }
                    134:                
                    135:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length));
                    136: 
                    137:                if (connection->errcode != OCI_SUCCESS) {
                    138:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    139:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    140:                        return 1;
                    141:                }
                    142: 
                    143:                descriptor->lob_size = *length;
                    144: 
                    145:                if (descriptor->type == OCI_DTYPE_FILE) {
                    146:                        PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
                    147: 
                    148:                        if (connection->errcode != OCI_SUCCESS) {
                    149:                                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    150:                                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    151:                                return 1;
                    152:                        }
                    153:                }
                    154:        }
                    155:        return 0;       
                    156: } /* }}} */
                    157: 
                    158: /* {{{ php_oci_lob_callback()
                    159:    Append LOB portion to a memory buffer */
                    160: #if defined(HAVE_OCI_LOB_READ2)
                    161: sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp)
                    162: #else
                    163: sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece)
                    164: #endif
                    165: {
                    166:        ub4 lenp = (ub4) len;
                    167:        php_oci_lob_ctx *ctx = (php_oci_lob_ctx *)ctxp;
                    168: 
                    169:        switch (piece)
                    170:        {
                    171:                case OCI_LAST_PIECE:
                    172:                        if ((*(ctx->lob_len) + lenp) > (ctx->alloc_len)) {
                    173:                                /* this should not happen ever */
                    174:                                *(ctx->lob_data) = NULL;
                    175:                                *(ctx->lob_len) = 0;
                    176:                                return OCI_ERROR;
                    177:                        }
                    178:                        memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
                    179:                        *(ctx->lob_len) += lenp;
                    180:                        *(*(ctx->lob_data) + *(ctx->lob_len)) = 0x00;
                    181:                        return OCI_CONTINUE;
                    182: 
                    183:                case OCI_FIRST_PIECE:
                    184:                case OCI_NEXT_PIECE:
                    185:                        if ((*(ctx->lob_len) + lenp) > ctx->alloc_len) {
                    186:                                /* this should not happen ever */
                    187:                                *(ctx->lob_data) = NULL;
                    188:                                *(ctx->lob_len) = 0;
                    189:                                return OCI_ERROR;
                    190:                        }
                    191:                        memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
                    192:                        *(ctx->lob_len) += lenp;
                    193:                        return OCI_CONTINUE;
                    194: 
                    195:                default: {
                    196:                        TSRMLS_FETCH();
                    197:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected LOB piece id received (value:%d)", piece);
                    198:                        *(ctx->lob_data) = NULL;
                    199:                        *(ctx->lob_len) = 0;
                    200:                        return OCI_ERROR;
                    201:                }
                    202:        }
                    203: }
                    204: /* }}} */
                    205: 
                    206: /* {{{ php_oci_lob_calculate_buffer() */
                    207: static inline int php_oci_lob_calculate_buffer(php_oci_descriptor *descriptor, long read_length TSRMLS_DC)
                    208: {
                    209:        php_oci_connection *connection = descriptor->connection;
                    210:        ub4 chunk_size;
                    211: 
                    212:        if (descriptor->type == OCI_DTYPE_FILE) {
                    213:                return read_length;
                    214:        }
                    215: 
                    216:        if (!descriptor->chunk_size) {
                    217:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetChunkSize, (connection->svc, connection->err, descriptor->descriptor, &chunk_size));
                    218: 
                    219:                if (connection->errcode != OCI_SUCCESS) {
                    220:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    221:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    222:                        return read_length; /* we have to return original length here */
                    223:                }
                    224:                descriptor->chunk_size = chunk_size;
                    225:        }
                    226:        
                    227:        if ((read_length % descriptor->chunk_size) != 0) {
                    228:                return descriptor->chunk_size * ((read_length / descriptor->chunk_size) + 1);
                    229:        }
                    230:        return read_length;
                    231: }
                    232: /* }}} */
                    233: 
                    234: /* {{{ php_oci_lob_read()
                    235:  Read specified portion of the LOB into the buffer */
                    236: int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long initial_offset, char **data, ub4 *data_len TSRMLS_DC)
                    237: {
                    238:        php_oci_connection *connection = descriptor->connection;
                    239:        ub4 length = 0;
                    240:        int buffer_size = PHP_OCI_LOB_BUFFER_SIZE;
                    241:        php_oci_lob_ctx ctx;
                    242:        ub1 *bufp;
                    243: #if defined(HAVE_OCI_LOB_READ2)
                    244:        oraub8 bytes_read, offset = 0;
                    245:        oraub8 requested_len = read_length; /* this is by default */
                    246:        oraub8 chars_read = 0;
                    247: #else
                    248:        int bytes_read, offset = 0;
                    249:        int requested_len = read_length; /* this is by default */
                    250: #endif
                    251:        int is_clob = 0;
                    252:        sb4 bytes_per_char = 1;
                    253: 
                    254:        *data_len = 0;
                    255:        *data = NULL;
                    256: 
                    257:        ctx.lob_len = data_len;
                    258:        ctx.lob_data = data;
                    259:        ctx.alloc_len = 0;
                    260: 
                    261:        if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
                    262:                return 1;
                    263:        }
                    264: 
                    265:        if (length <= 0) {
                    266:                return 0;
                    267:        }
                    268:        
                    269:        if (initial_offset > length) {
                    270:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be less than size of the LOB");
                    271:                return 1;
                    272:        }
                    273:                
                    274:        if (read_length == -1) {
                    275:                requested_len = length;
                    276:        }
                    277:        
                    278:        if (requested_len > (length - initial_offset)) {
                    279:                requested_len = length - initial_offset;
                    280:        }
                    281:        
                    282:        if (requested_len <= 0) {
                    283:                return 0;
                    284:        }
                    285:        
                    286:        offset = initial_offset;
                    287: 
                    288:        if (descriptor->type == OCI_DTYPE_FILE) {
                    289:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
                    290: 
                    291:                if (connection->errcode != OCI_SUCCESS) {
                    292:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    293:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    294:                        return 1;
                    295:                }
                    296:        } else {
                    297:                ub2 charset_id = 0;
                    298: 
                    299:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id));
                    300: 
                    301:                if (connection->errcode != OCI_SUCCESS) {
                    302:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    303:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    304:                        return 1;
                    305:                }
                    306: 
                    307:                if (charset_id > 0) { /* charset_id is always > 0 for [N]CLOBs */
                    308:                        is_clob = 1;
                    309:                }
                    310:        }
                    311: 
                    312:        if (is_clob) {
                    313:                PHP_OCI_CALL_RETURN(connection->errcode, OCINlsNumericInfoGet, (connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ));
                    314: 
                    315:                if (connection->errcode != OCI_SUCCESS) {
                    316:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    317:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    318:                        return 1;
                    319:                }
                    320:        } else {
                    321:                /* BLOBs don't have encoding, so bytes_per_char == 1 */
                    322:        }
                    323: 
                    324:        ctx.alloc_len = (requested_len + 1) * bytes_per_char;
                    325:        *data = ecalloc(bytes_per_char, requested_len + 1);
                    326: 
                    327: #ifdef HAVE_OCI_LOB_READ2
                    328:        if (is_clob) {
                    329:                chars_read = requested_len;
                    330:                bytes_read = 0;
                    331:        } else {
                    332:                chars_read = 0;
                    333:                bytes_read = requested_len;
                    334:        }
                    335: 
                    336:        buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size;             /* optimize buffer size */
                    337:        buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC);  /* use chunk size */
                    338: 
                    339:        bufp = (ub1 *) ecalloc(1, buffer_size);
                    340:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead2,
                    341:                (
                    342:                        connection->svc,
                    343:                        connection->err,
                    344:                        descriptor->descriptor,
                    345:                        (oraub8 *)&bytes_read,                                                  /* IN/OUT bytes toread/read */
                    346:                        (oraub8 *)&chars_read,                                                  /* IN/OUT chars toread/read */
                    347:                        (oraub8) offset + 1,                                                    /* offset (starts with 1) */
                    348:                        (dvoid *) bufp,
                    349:                        (oraub8) buffer_size,                                                   /* size of buffer */
                    350:                        OCI_FIRST_PIECE,
                    351:                        (dvoid *)&ctx,
                    352:                        (OCICallbackLobRead2) php_oci_lob_callback,                             /* callback... */
                    353:                        (ub2) descriptor->charset_id,                      /* The character set ID of the buffer data. */
                    354:                        (ub1) descriptor->charset_form                                    /* The character set form of the buffer data. */
                    355:                )
                    356:        );
                    357:        
                    358:        efree(bufp);
                    359:        
                    360:        if (is_clob) {
                    361:                offset = descriptor->lob_current_position + chars_read;
                    362:        } else {
                    363:                offset = descriptor->lob_current_position + bytes_read;
                    364:        }
                    365: 
                    366: #else
                    367: 
                    368:        bytes_read = requested_len;
                    369:        buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size;             /* optimize buffer size */
                    370:        buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC);  /* use chunk size */
                    371: 
                    372:        bufp = (ub1 *) ecalloc(1, buffer_size);
                    373:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead,
                    374:                (
                    375:                         connection->svc,
                    376:                         connection->err,
                    377:                         descriptor->descriptor,
                    378:                         &bytes_read,                                                            /* IN/OUT bytes toread/read */
                    379:                         offset + 1,                                                     /* offset (starts with 1) */
                    380:                         (dvoid *) bufp,
                    381:                         (ub4) buffer_size,                                                      /* size of buffer */
                    382:                         (dvoid *)&ctx,
                    383:                         (OCICallbackLobRead) php_oci_lob_callback,                              /* callback... */
                    384:                         (ub2) descriptor->charset_id,                          /* The character set ID of the buffer data. */
                    385:                         (ub1) descriptor->charset_form                                    /* The character set form of the buffer data. */
                    386:                )
                    387:        );
                    388:        
                    389:        efree(bufp);
                    390:        offset = descriptor->lob_current_position + bytes_read;
                    391: 
                    392: #endif
                    393:        
                    394:        if (connection->errcode != OCI_SUCCESS) {
                    395:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    396:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    397:                if (*data) {
                    398:                        efree(*data);
                    399:                        *data = NULL;
                    400:                }
                    401:                *data_len = 0;
                    402:                return 1;
                    403:        }
                    404:        
                    405:        descriptor->lob_current_position = (int)offset;
                    406: 
                    407:        if (descriptor->type == OCI_DTYPE_FILE) {
                    408:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
                    409: 
                    410:                if (connection->errcode != OCI_SUCCESS) {
                    411:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    412:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    413:                        if (*data) {
                    414:                                efree(*data);
                    415:                                *data = NULL;
                    416:                        }
                    417:                        *data_len = 0;
                    418:                        return 1;
                    419:                }
                    420:        }
                    421: 
                    422:        return 0;
                    423: } /* }}} */
                    424: 
                    425: /* {{{ php_oci_lob_write()
                    426:  Write data to the LOB */
                    427: int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, int data_len, ub4 *bytes_written TSRMLS_DC)
                    428: {
                    429:        OCILobLocator *lob                 = (OCILobLocator *) descriptor->descriptor;
                    430:        php_oci_connection *connection = (php_oci_connection *) descriptor->connection;
                    431:        ub4 lob_length;
                    432:        
                    433:        *bytes_written = 0;
                    434:        if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
                    435:                return 1;
                    436:        }
                    437:        
                    438:        if (!data || data_len <= 0) {
                    439:                return 0;
                    440:        }
                    441:        
                    442:        if (offset < 0) {
                    443:                offset = 0;
                    444:        }
                    445:        
                    446:        if (offset > descriptor->lob_current_position) {
                    447:                offset = descriptor->lob_current_position;
                    448:        }
                    449:        
                    450:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite,
                    451:                        (
                    452:                                connection->svc,
                    453:                                connection->err,
                    454:                                lob,
                    455:                                (ub4 *)&data_len,
                    456:                                (ub4) offset + 1,
                    457:                                (dvoid *) data,
                    458:                                (ub4) data_len,
                    459:                                OCI_ONE_PIECE,
                    460:                                (dvoid *)0,
                    461:                                (OCICallbackLobWrite) 0,
                    462:                                (ub2) descriptor->charset_id,
                    463:                                (ub1) descriptor->charset_form
                    464:                        )
                    465:                );
                    466: 
                    467:        if (connection->errcode) {
                    468:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    469:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    470:                *bytes_written = 0;
                    471:                return 1;
                    472:        }
                    473:        *bytes_written = data_len;
                    474:        descriptor->lob_current_position += data_len;
                    475:        
                    476:        if (descriptor->lob_current_position > descriptor->lob_size) {
                    477:                descriptor->lob_size = descriptor->lob_current_position;
                    478:        }
                    479:        
                    480:        /* marking buffer as used */
                    481:        if (descriptor->buffering == PHP_OCI_LOB_BUFFER_ENABLED) {
                    482:                descriptor->buffering = PHP_OCI_LOB_BUFFER_USED;
                    483:        }
                    484:        
                    485:        return 0;
                    486: } /* }}} */
                    487: 
                    488: /* {{{ php_oci_lob_set_buffering()
                    489:  Turn buffering off/onn for this particular LOB */
                    490: int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS_DC)
                    491: {
                    492:        php_oci_connection *connection = descriptor->connection;
                    493: 
                    494:        if (!on_off && descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
                    495:                /* disabling when it's already off */
                    496:                return 0;
                    497:        }
                    498:        
                    499:        if (on_off && descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
                    500:                /* enabling when it's already on */
                    501:                return 0;
                    502:        }
                    503:        
                    504:        if (on_off) {
                    505:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor));
                    506:        } else {
                    507:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor));
                    508:        }
                    509: 
                    510:        if (connection->errcode != OCI_SUCCESS) {
                    511:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    512:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    513:                return 1;
                    514:        }
                    515:        descriptor->buffering = on_off ? PHP_OCI_LOB_BUFFER_ENABLED : PHP_OCI_LOB_BUFFER_DISABLED;
                    516:        return 0;
                    517: } /* }}} */
                    518: 
                    519: /* {{{ php_oci_lob_get_buffering()
                    520:  Return current buffering state for the LOB */
                    521: int php_oci_lob_get_buffering (php_oci_descriptor *descriptor)
                    522: {
                    523:        if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
                    524:                return 1;
                    525:        } else {
                    526:                return 0;
                    527:        }
                    528: } /* }}} */
                    529: 
                    530: /* {{{ php_oci_lob_copy()
                    531:  Copy one LOB (or its part) to another one */
                    532: int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from, long length TSRMLS_DC)
                    533: {
                    534:        php_oci_connection *connection = descriptor_dest->connection;
                    535:        ub4 length_dest, length_from, copy_len;
                    536:        
                    537:        if (php_oci_lob_get_length(descriptor_dest, &length_dest TSRMLS_CC)) {
                    538:                return 1;
                    539:        }
                    540:        
                    541:        if (php_oci_lob_get_length(descriptor_from, &length_from TSRMLS_CC)) {
                    542:                return 1;
                    543:        }
                    544: 
                    545:        if (length == -1) {
                    546:                copy_len = length_from - descriptor_from->lob_current_position;
                    547:        } else {
                    548:                copy_len = length;
                    549:        }
                    550: 
                    551:        if ((int)copy_len <= 0) {
                    552:                /* silently fail, there is nothing to copy */
                    553:                return 1;
                    554:        }
                    555: 
                    556:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy,
                    557:                        (
                    558:                         connection->svc,
                    559:                         connection->err,
                    560:                         descriptor_dest->descriptor,
                    561:                         descriptor_from->descriptor,
                    562:                         copy_len,
                    563:                         descriptor_dest->lob_current_position+1,
                    564:                         descriptor_from->lob_current_position+1
                    565:                        )
                    566:        );
                    567: 
                    568:        if (connection->errcode != OCI_SUCCESS) {
                    569:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    570:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    571:                return 1;
                    572:        }
                    573:        
                    574:        return 0;
                    575: } /* }}} */
                    576: 
                    577: /* {{{ php_oci_lob_close()
                    578:  Close LOB */
                    579: int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
                    580: {
                    581:        php_oci_connection *connection = descriptor->connection;
                    582:        
                    583:        if (descriptor->is_open) {
                    584:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
                    585:        }
                    586: 
                    587:        if (connection->errcode != OCI_SUCCESS) {
                    588:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    589:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    590:                return 1;
                    591:        }
                    592: 
                    593:        if (php_oci_temp_lob_close(descriptor TSRMLS_CC)) {
                    594:                return 1;
                    595:        }
                    596:        
                    597:        return 0;
                    598: } /* }}} */
                    599: 
                    600: /* {{{ php_oci_temp_lob_close()
                    601:    Close Temporary LOB */
                    602: int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
                    603: {
                    604:        php_oci_connection *connection = descriptor->connection;
                    605:        int is_temporary;
                    606: 
                    607:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary));
                    608:        
                    609:        if (connection->errcode != OCI_SUCCESS) {
                    610:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    611:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    612:                return 1;
                    613:        }
                    614:        
                    615:        if (is_temporary) {
                    616:                PHP_OCI_CALL_RETURN(connection->errcode, OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor));
                    617:                
                    618:                if (connection->errcode != OCI_SUCCESS) {
                    619:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    620:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    621:                        return 1;
                    622:                }
                    623:        }
                    624:        return 0;
                    625: } /* }}} */
                    626: 
                    627: 
                    628: /* {{{ php_oci_lob_flush()
                    629:  Flush buffers for the LOB (only if they have been used) */
                    630: int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC)
                    631: {
                    632:        OCILobLocator *lob = descriptor->descriptor;
                    633:        php_oci_connection *connection = descriptor->connection;
                    634:        
                    635:        if (!lob) {
                    636:                return 1;
                    637:        }
                    638: 
                    639:        switch (flush_flag) {
                    640:                case 0:
                    641:                case OCI_LOB_BUFFER_FREE:
                    642:                        /* only these two are allowed */
                    643:                        break;
                    644:                default:
                    645:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid flag value: %ld", flush_flag);
                    646:                        return 1;
                    647:                        break;
                    648:        }
                    649:        
                    650:        /* do not really flush buffer, but report success
                    651:         * to suppress OCI error when flushing not used buffer
                    652:         * */
                    653:        if (descriptor->buffering != PHP_OCI_LOB_BUFFER_USED) {
                    654:                return 0;
                    655:        }
                    656: 
                    657:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag));
                    658: 
                    659:        if (connection->errcode != OCI_SUCCESS) {
                    660:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    661:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    662:                return 1;
                    663:        }
                    664: 
                    665:        /* marking buffer as enabled and not used */
                    666:        descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
                    667:        return 0;
                    668: } /* }}} */
                    669: 
                    670: /* {{{ php_oci_lob_free()
                    671:  Close LOB descriptor and free associated resources */
                    672: void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
                    673: {
                    674:        if (!descriptor || !descriptor->connection) {
                    675:                return;
                    676:        }
                    677: 
                    678:        if (descriptor->connection->descriptors) {
                    679:                /* delete descriptor from the hash */
                    680:                zend_hash_index_del(descriptor->connection->descriptors, descriptor->index);
                    681:                if (zend_hash_num_elements(descriptor->connection->descriptors) == 0) {
                    682:                        descriptor->connection->descriptor_count = 0;
                    683:                } else {
                    684:                        if (descriptor->index + 1 == descriptor->connection->descriptor_count) {
                    685:                                /* If the descriptor being freed is the end-most one
                    686:                                 * allocated, then the descriptor_count is reduced so
                    687:                                 * a future descriptor can reuse the hash table index.
                    688:                                 * This can prevent the hash index range increasing in
                    689:                                 * the common case that each descriptor is
                    690:                                 * allocated/used/freed before another descriptor is
                    691:                                 * needed.  However it is possible that a script frees
                    692:                                 * descriptors in arbitrary order which would prevent
                    693:                                 * descriptor_count ever being reduced to zero until
                    694:                                 * zend_hash_num_elements() returns 0.
                    695:                                 */
                    696:                                descriptor->connection->descriptor_count--;
                    697:                        }
                    698:                }
                    699:        }
                    700:        
                    701:        /* flushing Lobs & Files with buffering enabled */
                    702:        if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
                    703:                php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
                    704:        }
                    705: 
                    706:        if (descriptor->type == OCI_DTYPE_LOB) {
                    707:                php_oci_temp_lob_close(descriptor TSRMLS_CC);
                    708:        }
                    709: 
                    710:        PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type));
                    711: 
                    712:        zend_list_delete(descriptor->connection->rsrc_id);
                    713:        efree(descriptor);
                    714: } /* }}} */
                    715: 
                    716: /* {{{ php_oci_lob_import()
                    717:  Import LOB contents from the given file */
                    718: int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC)
                    719: {
                    720:        int fp;
                    721:        ub4 loblen;
                    722:        OCILobLocator *lob = (OCILobLocator *)descriptor->descriptor;
                    723:        php_oci_connection *connection = descriptor->connection;
                    724:        char buf[8192];
                    725:        ub4 offset = 1;
                    726:        
                    727: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
                    728:        /* Safe mode has been removed in PHP 5.4 */
                    729:        if (php_check_open_basedir(filename TSRMLS_CC)) {
                    730: #else
                    731:        if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) {
                    732: #endif
                    733:                return 1;
                    734:        }
                    735:        
                    736:        if ((fp = VCWD_OPEN(filename, O_RDONLY|O_BINARY)) == -1) {
                    737:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't open file %s", filename);
                    738:                return 1;
                    739:        }
                    740: 
                    741:        while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {    
                    742:                PHP_OCI_CALL_RETURN(connection->errcode,
                    743:                                OCILobWrite,
                    744:                                (
                    745:                                        connection->svc,
                    746:                                        connection->err,
                    747:                                        lob,
                    748:                                        &loblen,
                    749:                                        offset,
                    750:                                        (dvoid *) &buf,
                    751:                                        loblen,
                    752:                                        OCI_ONE_PIECE,
                    753:                                        (dvoid *)0,
                    754:                                        (OCICallbackLobWrite) 0,
                    755:                                        (ub2) descriptor->charset_id,
                    756:                                        (ub1) descriptor->charset_form
                    757:                                )
                    758:                );
                    759: 
                    760:                if (connection->errcode != OCI_SUCCESS) {
                    761:                        connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    762:                        PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    763:                        close(fp);
                    764:                        return 1;
                    765:                }
                    766:                offset += loblen;
                    767:        }
                    768:        close(fp);
                    769:        
                    770:        return 0;
                    771: } /* }}} */
                    772: 
                    773: /* {{{ php_oci_lob_append()
                    774:  Append data to the end of the LOB */
                    775: int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from TSRMLS_DC)
                    776: {
                    777:        php_oci_connection *connection = descriptor_dest->connection;
                    778:        OCILobLocator *lob_dest = descriptor_dest->descriptor;
                    779:        OCILobLocator *lob_from = descriptor_from->descriptor;
                    780:        ub4 dest_len, from_len;
                    781: 
                    782:        if (php_oci_lob_get_length(descriptor_dest, &dest_len TSRMLS_CC)) {
                    783:                return 1;
                    784:        }
                    785:        
                    786:        if (php_oci_lob_get_length(descriptor_from, &from_len TSRMLS_CC)) {
                    787:                return 1;
                    788:        }
                    789: 
                    790:        if (from_len <= 0) {
                    791:                return 0;
                    792:        }
                    793: 
                    794:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from));
                    795: 
                    796:        if (connection->errcode != OCI_SUCCESS) {
                    797:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    798:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    799:                return 1;
                    800:        }
                    801:        return 0;
                    802: } /* }}} */
                    803: 
                    804: /* {{{ php_oci_lob_truncate()
                    805:  Truncate LOB to the given length */
                    806: int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TSRMLS_DC)
                    807: {
                    808:        php_oci_connection *connection = descriptor->connection;
                    809:        OCILobLocator *lob = descriptor->descriptor;
                    810:        ub4 lob_length;
                    811:        
                    812:        if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
                    813:                return 1;
                    814:        }
                    815:        
                    816:        if (lob_length <= 0) {
                    817:                return 0;
                    818:        }
                    819: 
                    820:        if (new_lob_length < 0) {
                    821:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be greater than or equal to 0");
                    822:                return 1;
                    823:        }
                    824: 
                    825:        if (new_lob_length > lob_length) {
                    826:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be less than or equal to the current LOB size");
                    827:                return 1;
                    828:        }
                    829:        
                    830:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobTrim, (connection->svc, connection->err, lob, new_lob_length));
                    831: 
                    832:        if (connection->errcode != OCI_SUCCESS) {
                    833:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    834:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    835:                return 1;
                    836:        }
                    837:        
                    838:        descriptor->lob_size = new_lob_length;
                    839:        return 0;
                    840: } /* }}} */
                    841: 
                    842: /* {{{ php_oci_lob_erase()
                    843:  Erase (or fill with whitespaces, depending on LOB type) the LOB (or its part) */
                    844: int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, ub4 length, ub4 *bytes_erased TSRMLS_DC)
                    845: {
                    846:        php_oci_connection *connection = descriptor->connection;
                    847:        OCILobLocator *lob = descriptor->descriptor;
                    848:        ub4 lob_length;
                    849: 
                    850:        *bytes_erased = 0;
                    851:        
                    852:        if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
                    853:                return 1;
                    854:        }
                    855:        
                    856:        if (offset == -1) {
                    857:                offset = descriptor->lob_current_position;
                    858:        }
                    859: 
                    860:        if (length == -1) {
                    861:                length = lob_length;
                    862:        }
                    863:        
                    864:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1));
                    865: 
                    866:        if (connection->errcode != OCI_SUCCESS) {
                    867:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    868:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    869:                return 1;
                    870:        }
                    871:        
                    872:        *bytes_erased = length;
                    873:        return 0;
                    874: } /* }}} */
                    875: 
                    876: /* {{{ php_oci_lob_is_equal()
                    877:  Compare two LOB descriptors and figure out if they are pointing to the same LOB */
                    878: int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC)
                    879: {
                    880:        php_oci_connection *connection = descriptor_first->connection;
                    881:        OCILobLocator *first_lob   = descriptor_first->descriptor;
                    882:        OCILobLocator *second_lob  = descriptor_second->descriptor;
                    883: 
                    884:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsEqual, (connection->env, first_lob, second_lob, result));
                    885: 
                    886:        if (connection->errcode) {
                    887:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    888:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    889:                return 1;
                    890:        }
                    891:        return 0;
                    892: } /* }}} */
                    893: 
                    894: /* {{{ php_oci_lob_write_tmp()
                    895:  Create temporary LOB and write data to it */
                    896: int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, long type, char *data, int data_len TSRMLS_DC)
                    897: {
                    898:        php_oci_connection *connection = descriptor->connection;
                    899:        OCILobLocator *lob                 = descriptor->descriptor;
                    900:        ub4 bytes_written = 0;
                    901:        
                    902:        switch (type) {
                    903:                case OCI_TEMP_BLOB:
                    904:                case OCI_TEMP_CLOB:
                    905:                        /* only these two are allowed */
                    906:                        break;
                    907:                default:
                    908:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid temporary lob type: %ld", type);
                    909:                        return 1;
                    910:                        break;
                    911:        }
                    912: 
                    913:        if (data_len < 0) {
                    914:                return 1;
                    915:        }
                    916: 
                    917:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary,
                    918:                        (
                    919:                         connection->svc,
                    920:                         connection->err,
                    921:                         lob,
                    922:                         OCI_DEFAULT,
                    923:                         OCI_DEFAULT,
                    924:                         (ub1)type,
                    925:                         OCI_ATTR_NOCACHE,
                    926:                         OCI_DURATION_SESSION
                    927:                        )
                    928:        );
                    929: 
                    930:        if (connection->errcode) {
                    931:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    932:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    933:                return 1;
                    934:        }
                    935: 
                    936:        PHP_OCI_CALL_RETURN(connection->errcode, OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE));
                    937: 
                    938:        if (connection->errcode) {
                    939:                connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
                    940:                PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
                    941:                return 1;
                    942:        }
                    943: 
                    944:        descriptor->is_open = 1;
                    945: 
                    946:        return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
                    947: } /* }}} */
                    948: 
                    949: #endif /* HAVE_OCI8 */
                    950: 
                    951: /*
                    952:  * Local variables:
                    953:  * tab-width: 4
                    954:  * c-basic-offset: 4
                    955:  * End:
                    956:  * vim600: noet sw=4 ts=4 fdm=marker
                    957:  * vim<600: noet sw=4 ts=4
                    958:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>