2
+----------------------------------------------------------------------+
4
+----------------------------------------------------------------------+
5
| Copyright (c) 2006-2009 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: Georg Richter <georg@mysql.com> |
16
| Andrey Hristov <andrey@mysql.com> |
17
| Ulf Wendel <uwendel@mysql.com> |
18
+----------------------------------------------------------------------+
22
#include "php_globals.h"
24
#include "mysqlnd_wireprotocol.h"
25
#include "mysqlnd_priv.h"
26
#include "mysqlnd_debug.h"
28
enum_func_status mysqlnd_simple_command_handle_response(MYSQLND *conn,
29
enum php_mysql_packet_type ok_packet,
30
zend_bool silent, enum php_mysqlnd_server_command command,
31
zend_bool ignore_upsert_status
35
#define ALLOC_CALLBACK_ARGS(a, b, c)\
37
a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
38
for (i = b; i < c; i++) {\
39
a[i] = mnd_emalloc(sizeof(zval *));\
40
MAKE_STD_ZVAL(*a[i]);\
44
#define FREE_CALLBACK_ARGS(a, b, c)\
46
for (i=b; i < c; i++) {\
53
/* {{{ mysqlnd_local_infile_init */
55
int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
57
MYSQLND_INFILE_INFO *info;
58
php_stream_context *context = NULL;
60
DBG_ENTER("mysqlnd_local_infile_init");
62
*ptr = info = ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
64
/* check open_basedir */
65
if (PG(open_basedir)) {
66
if (php_check_open_basedir_ex(filename, 0 TSRMLS_CC) == -1) {
67
strcpy(info->error_msg, "open_basedir restriction in effect. Unable to open file");
68
info->error_no = CR_UNKNOWN_ERROR;
73
info->filename = filename;
74
info->fd = php_stream_open_wrapper_ex((char *)filename, "r", 0, NULL, context);
76
if (info->fd == NULL) {
77
snprintf((char *)info->error_msg, sizeof(info->error_msg), "Can't find file '%-.64s'.", filename);
78
info->error_no = MYSQLND_EE_FILENOTFOUND;
87
/* {{{ mysqlnd_local_infile_read */
89
int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC)
91
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
94
DBG_ENTER("mysqlnd_local_infile_read");
96
count = (int)php_stream_read(info->fd, buf, buf_len);
99
strcpy(info->error_msg, "Error reading file");
100
info->error_no = CR_UNKNOWN_ERROR;
108
/* {{{ mysqlnd_local_infile_error */
110
int mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
112
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
114
DBG_ENTER("mysqlnd_local_infile_error");
117
strlcpy(error_buf, info->error_msg, error_buf_len);
118
DBG_INF_FMT("have info, %d", info->error_no);
119
DBG_RETURN(info->error_no);
122
strlcpy(error_buf, "Unknown error", error_buf_len);
123
DBG_INF_FMT("no info, %d", CR_UNKNOWN_ERROR);
124
DBG_RETURN(CR_UNKNOWN_ERROR);
129
/* {{{ mysqlnd_local_infile_end */
131
void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
133
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
136
/* php_stream_close segfaults on NULL */
138
php_stream_close(info->fd);
147
/* {{{ mysqlnd_local_infile_default */
148
PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
150
conn->infile.local_infile_init = mysqlnd_local_infile_init;
151
conn->infile.local_infile_read = mysqlnd_local_infile_read;
152
conn->infile.local_infile_error = mysqlnd_local_infile_error;
153
conn->infile.local_infile_end = mysqlnd_local_infile_end;
157
/* {{{ mysqlnd_set_local_infile_handler */
158
PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
160
if (!conn->infile.callback) {
161
MAKE_STD_ZVAL(conn->infile.callback);
163
zval_dtor(conn->infile.callback);
165
ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
170
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
173
/* {{{ mysqlnd_handle_local_infile */
175
mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
178
char empty_packet[MYSQLND_HEADER_SIZE];
179
enum_func_status result = FAIL;
180
unsigned int buflen = 4096;
184
MYSQLND_INFILE infile;
186
DBG_ENTER("mysqlnd_handle_local_infile");
188
if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
189
php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
190
/* write empty packet to server */
191
ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
196
infile = conn->infile;
197
/* allocate buffer for reading data */
198
buf = (char *)mnd_ecalloc(1, buflen);
202
/* init handler: allocate read buffer and open file */
203
if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
206
strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
207
conn->error_info.error_no =
208
infile.local_infile_error(info, conn->error_info.error,
209
sizeof(conn->error_info.error) TSRMLS_CC);
210
/* write empty packet to server */
211
ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC);
216
while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE,
217
buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
218
if ((ret = mysqlnd_stream_write_w_header(conn, buf, bufsize TSRMLS_CC)) < 0) {
219
DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
220
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
225
/* send empty packet for eof */
226
if ((ret = mysqlnd_stream_write_w_header(conn, empty_packet, 0 TSRMLS_CC)) < 0) {
227
SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
231
/* error during read occured */
234
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
235
strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
236
conn->error_info.error_no = infile.local_infile_error(info, conn->error_info.error,
237
sizeof(conn->error_info.error) TSRMLS_CC);
244
/* get response from server and update upsert values */
245
if (FAIL == mysqlnd_simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE TSRMLS_CC)) {
249
(*conn->infile.local_infile_end)(info TSRMLS_CC);
251
DBG_INF_FMT("%s", result == PASS? "PASS":"FAIL");
261
* vim600: noet sw=4 ts=4 fdm=marker
262
* vim<600: noet sw=4 ts=4