PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/oci8 - oci8_lob.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 312 418 74.6 %
Date: 2016-07-19 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Wed, 20 Jul 2016 02:56:22 +0000 (4 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.