1--TEST--
2mysqli_set_local_infile_handler()
3--SKIPIF--
4<?php
5require_once('skipif.inc');
6require_once('skipifemb.inc');
7require_once('skipifconnectfailure.inc');
8
9if (!function_exists('mysqli_set_local_infile_handler'))
10	die("skip - function not available.");
11
12require_once('connect.inc');
13if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
14	die("skip Cannot connect to MySQL");
15
16include_once("local_infile_tools.inc");
17if ($msg = check_local_infile_support($link, $engine))
18	die(sprintf("skip %s, [%d] %s", $msg, $link->errno, $link->error));
19
20mysqli_close($link);
21?>
22--INI--
23mysqli.allow_local_infile=1
24--FILE--
25<?php
26	require_once('connect.inc');
27	require_once('local_infile_tools.inc');
28	require_once('table.inc');
29
30	function callback_simple($fp, &$buffer, $buflen, &$error) {
31		static $invocation = 0;
32
33		printf("Callback: %d\n", $invocation);
34
35		$invocation++;
36		if (!is_resource($fp))
37			printf("[012] First argument passed to callback is not a resource but %s/%s\n",
38				$fp, gettype($fp));
39
40		if (!$buffer = fread($fp, $buflen)) {
41			if ($invocation == 1) {
42				printf("[013] Cannot read from stream\n");
43					$error = 'Cannot read from stream';
44			} else {
45				return strlen($buffer);
46			}
47		}
48
49		$lines = explode("\n", $buffer);
50		if (count($lines) != 4 && strlen($buffer) > 0) {
51			printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
52			$error = 'Parser too simple';
53		}
54
55		$buffer = '';
56		foreach ($lines as $k => $line) {
57			if ('' === trim($line))
58				continue;
59
60			$columns = explode(';', $line);
61			if (empty($columns)) {
62				printf("[015] Cannot parse columns\n");
63				$error = 'Cannot parse columns';
64			}
65
66			// increase id column value
67			$columns[0] += 1;
68			$buffer .= implode(';', $columns);
69			$buffer .= "\n";
70		}
71
72		return strlen($buffer);
73	}
74
75	function callback_fclose($fp, &$buffer, $buflen, &$error) {
76		static $invocation = 0;
77
78		printf("Callback: %d\n", $invocation++);
79
80		fclose($fp);
81		return strlen($buffer);
82	}
83
84	function callback_closefile($fp, &$buffer, $buflen, &$error) {
85		static $invocation = 0;
86
87		printf("Callback: %d\n", $invocation++);
88		flush();
89		if (is_resource($fp))
90			fclose($fp);
91		$buffer = "1;'a';\n";
92		if ($invocation > 10)
93			return 0;
94
95		return strlen($buffer);
96	}
97
98	function callback_invalid_args($fp, &$buffer, $buflen) {
99		static $invocation = 0;
100
101		printf("Callback: %d\n", $invocation++);
102		$buffer = fread($fp, $buflen);
103
104		return strlen($buffer);
105	}
106
107	function callback_error($fp, &$buffer, $buflen, &$error) {
108		static $invocation = 0;
109
110		printf("Callback: %d\n", $invocation++);
111		$buffer = fread($fp, $buflen);
112		$error = 'How to access this error?';
113
114		return -1;
115	}
116
117	if (!is_null($tmp = @mysqli_set_local_infile_handler()))
118		printf("[001] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
119
120	$handle = null;
121	if (!is_null($tmp = @mysqli_set_local_infile_handler($handle)))
122		printf("[002] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
123
124	$handle = @new mysqli();
125	if (!is_null($tmp = @mysqli_set_local_infile_handler($handle, 'callback_simple')))
126		printf("[003] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
127
128	if (false !== ($tmp = @mysqli_set_local_infile_handler($link, 'unknown')))
129		printf("[004] Expecting false/boolean got %s/%s\n", $tmp, gettype($tmp));
130
131	$file = create_standard_csv(5);
132
133	$expected = array(
134		array('id' => 98,   'label' => 'x'),
135		array('id' => 99,   'label' => 'y'),
136		array('id' => 100,  'label' => 'z'),
137	);
138	try_handler(10, $link, $file, 'callback_simple', $expected);
139
140	$expected = array();
141	try_handler(20, $link, $file, 'callback_fclose', $expected);
142
143	// FIXME - TODO - KLUDGE -
144  // IMHO this is wrong. ext/mysqli should bail as the function signature
145  // is not complete. That's a BC break, OK, but it makes perfectly sense.
146	$expected = array();
147	try_handler(30, $link, $file, 'callback_invalid_args', $expected);
148
149	$expected = array();
150	try_handler(40, $link, $file, 'callback_error', $expected);
151
152
153	mysqli_close($link);
154
155	if (!is_null($tmp = @mysqli_set_local_infile_handler($link, 'callback_simple')))
156		printf("[300] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
157
158	print "done!";
159?>
160--CLEAN--
161<?php
162	require_once("clean_table.inc");
163?>
164--EXPECTF--
165Callback set to 'callback_simple'
166Callback: 0
167Callback: 1
168Callback set to 'callback_fclose'
169Callback: 0
170[022] LOAD DATA failed, [2000] File handle close%s
171Callback set to 'callback_invalid_args'
172Callback: 0
173Callback: 1
174[037] More results than expected!
175array(2) {
176  [%u|b%"id"]=>
177  %unicode|string%(2) "97"
178  [%u|b%"label"]=>
179  %unicode|string%(1) "x"
180}
181array(2) {
182  [%u|b%"id"]=>
183  %unicode|string%(2) "98"
184  [%u|b%"label"]=>
185  %unicode|string%(1) "y"
186}
187array(2) {
188  [%u|b%"id"]=>
189  %unicode|string%(2) "99"
190  [%u|b%"label"]=>
191  %unicode|string%(1) "z"
192}
193Callback set to 'callback_error'
194Callback: 0
195[042] LOAD DATA failed, [2000] How to access this error?
196done!