PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.82
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.82
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
wp-data-access / WPDataAccess / Utilities / WPDA_Import_File.php

WPDA_Import_File.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.82, at WPDataAccess/Utilities/WPDA_Import_File.php

173 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Suppress "error - 0 - No summary was found for this file" on phpdoc generation
5 *
6 * @package WPDataAccess\Utilities
7 */
8
9 namespace WPDataAccess\Utilities {
10
11 use WPDataAccess\Connection\WPDADB;
12
13 /**
14 * Class WPDA_Import_File
15 *
16 * Loads the content of an import file and imports it.
17 *
18 * @author Peter Schulz
19 * @since 1.0.0
20 */
21 class WPDA_Import_File {
22
23 /**
24 * Pointer to import file
25 *
26 * @var string
27 */
28 protected $file_pointer;
29
30 /**
31 * Content of import file
32 *
33 * @var string
34 */
35 protected $file_content;
36
37 /**
38 * WPDA_Import constructor
39 *
40 * Create file pointer.
41 *
42 * @param string $file_path Full path of script (import) file.
43 *
44 * @since 1.0.0
45 */
46 public function __construct( $file_path ) {
47
48 $this->file_pointer = fopen( $file_path, 'rb' ); // phpcs:ignore
49
50 }
51
52 /**
53 * Close file.
54 *
55 * @since 2.0.12
56 */
57 public function __destruct() {
58 fclose( $this->file_pointer ); // phpcs:ignore
59 }
60
61 /**
62 * Import file content
63 *
64 * Import method writes the content of the import file to the database. Security checks:
65 * + Only INSERT INTO is allowed: no other DML, DDL and DCL statements allowed
66 * + Only inserts into the table name provided are allowed
67 * + Use explain to check the number of tables affect: more than 1 looks like SQL injection
68 *
69 * Since wpdb-query() only processes one query at a time we only need to check the type of statement at the
70 * beginning of the script ($file_content).
71 *
72 * This method only return -1 if a failure occurs or the number of rows inserted. The number of probable error
73 * cause is to huge and complex to check all possibilities. Exports created from the WP Data Access table list
74 * should normally import without problems. For manually created imports responsibility is with the developer.
75 *
76 * @param string $schema_name Schema in which this import allowes inserts.
77 * @param string $table_name Table in which this import allowes inserts.
78 * @param string $hide_errors ON = hide errors, OFF = show errors.
79 *
80 * @since 1.0.0
81 */
82 public function import( $schema_name, $table_name, $hide_errors ) {
83 global $wpdb;
84
85 $wpdadb = WPDADB::get_db_connection( $schema_name );
86 if ( null === $wpdadb ) {
87 /* translators: %s = database name */
88 wp_die( sprintf( esc_attr__( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $schema_name ) ) );
89 }
90
91 $suppress = $wpdadb->suppress_errors( 'on' === $hide_errors );
92
93 $this->file_content = '';
94 $rows = 0;
95 $rows_failed = 0;
96
97 if ( false !== $this->file_pointer ) {
98 while ( ! feof( $this->file_pointer ) ) {
99 $this->file_content .= fread( $this->file_pointer, 4096 ); // phpcs:ignore
100
101 // Replace WP prefix and WPDA prefix.
102 $this->file_content = str_replace( '{wp_schema}', $wpdb->dbname, $this->file_content );
103 $this->file_content = str_replace( '{wp_prefix}', $wpdb->prefix, (string) $this->file_content );
104 $this->file_content = str_replace( '{wpda_prefix}', 'wpda', (string) $this->file_content ); // for backward compatibility
105
106 // Find and process SQL statements.
107 $sql_end_unix = strpos( $this->file_content, ";\n" );
108 $sql_end_windows = strpos( $this->file_content, ";\r\n" );
109 while ( false !== $sql_end_unix || false !== $sql_end_windows ) {
110 if ( false === $sql_end_unix ) {
111 $sql_end = $sql_end_windows;
112 } elseif ( false === $sql_end_windows ) {
113 $sql_end = $sql_end_unix;
114 } else {
115 $sql_end = min( $sql_end_unix, $sql_end_windows );
116 }
117 $sql = rtrim( substr( $this->file_content, 0, $sql_end ) );
118
119 $this->file_content = substr( $this->file_content, strpos( $this->file_content, $sql ) + strlen( $sql ) + 1 );
120 $rows ++;
121
122 // Write file content to array for security check (150 characters is sufficient to check DML and table name).
123 $dml_check = explode( ' ', substr( trim( $sql ), 0, 150 ) ); // phpcs:ignore -- 8.1 proof
124
125 if ( ! isset( $dml_check[0] ) || ! isset( $dml_check[1] ) ) {
126 // No content.
127 $rows_failed ++;
128 } else {
129 // Check first two words (must be insert into, no other statements allowed).
130 if ( strtolower( $dml_check[0] . $dml_check[1] ) !== 'insertinto' ) {
131 // Only insert into is allowed.
132 $rows_failed ++;
133 } else {
134 // Check table name (using stristr should cover backticks and schema_names as well).
135 if ( ! stristr( $dml_check[2], $table_name ) ) {
136 $rows_failed ++;
137 } else {
138 // Insert row.
139 if ( false === $wpdadb->query( $sql ) ) {
140 $rows_failed ++;
141 }
142 }
143 }
144 }
145
146 // Find next SQL statement.
147 $sql_end_unix = strpos( $this->file_content, ";\n" );
148 $sql_end_windows = strpos( $this->file_content, ";\r\n" );
149 }
150 }
151 }
152
153 $wpdadb->suppress_errors( $suppress );
154
155 $msg = 'Imported ' . ( $rows - $rows_failed ) . ' rows';
156 if ( $rows_failed > 0 ) {
157 $msg .= " ($rows_failed failed).";
158 } else {
159 $msg .= '.';
160 }
161 $msg = new WPDA_Message_Box(
162 array(
163 'message_text' => $msg,
164 )
165 );
166 $msg->box();
167
168 }
169
170 }
171
172 }
173