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

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:01 +0000 (39 hours ago)

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