Completed
Push — 23 ( 2cbb94...e876bd )
by Harald
11:26 queued 05:21
created

OSCOM_Braintree::install()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 33
Code Lines 17

Duplication

Lines 33
Ratio 100 %

Importance

Changes 0
Metric Value
cc 8
eloc 17
nc 12
nop 1
dl 33
loc 33
rs 5.3846
c 0
b 0
f 0
1
<?php
2
/*
3
  $Id$
4
5
  osCommerce, Open Source E-Commerce Solutions
6
  http://www.oscommerce.com
7
8
  Copyright (c) 2017 osCommerce
9
10
  Released under the GNU General Public License
11
*/
12
13
  class OSCOM_Braintree {
14
    var $_code = 'braintree';
15
    var $_title = 'Braintree App';
16
    var $_version;
17
    var $_api_version;
18
    var $_identifier = 'osCommerce_BTapp_v1';
19
    var $_definitions = array();
20
21
    function OSCOM_Braintree() {
22
      if ( !class_exists('Braintree', false) ) {
23
        include(DIR_FS_CATALOG . 'includes/apps/braintree/lib/Braintree.php');
24
      }
25
26
      $this->_api_version = Braintree_Version::get();
27
28
      $this->installCheck();
29
    }
30
31
    function installCheck() {
32
      if (!defined('OSCOM_APP_PAYPAL_BRAINTREE_CC_SORT_ORDER')) {
33
        $installed = explode(';', MODULE_PAYMENT_INSTALLED);
34
        $installed_pos = array_search('braintree_cc.php', $installed);
35
36
        if ( $installed_pos === false ) {
37
          $installed[] = 'braintree_cc.php';
38
39
          $this->saveParameter('MODULE_PAYMENT_INSTALLED', implode(';', $installed));
40
        }
41
42
        $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_CC_SORT_ORDER', '0', 'Sort Order', 'Sort order of display. Lowest is displayed first.');
43
44
        $check_query = tep_db_query('show tables like "customers_braintree_tokens"');
45
        if (!tep_db_num_rows($check_query)) {
46
          $sql = <<<EOD
47
CREATE TABLE customers_braintree_tokens (
48
  id int NOT NULL auto_increment,
49
  customers_id int NOT NULL,
50
  braintree_token varchar(255) NOT NULL,
51
  card_type varchar(32) NOT NULL,
52
  number_filtered varchar(20) NOT NULL,
53
  expiry_date char(6) NOT NULL,
54
  date_added datetime NOT NULL,
55
  PRIMARY KEY (id),
56
  KEY idx_cbraintreet_customers_id (customers_id),
57
  KEY idx_cbraintreet_token (braintree_token)
58
) CHARACTER SET utf8 COLLATE utf8_unicode_ci;
59
EOD;
60
61
          tep_db_query($sql);
62
        }
63
      }
64
65
      if ( !defined('OSCOM_APP_PAYPAL_BRAINTREE_TRANSACTIONS_ORDER_STATUS_ID') ) {
66
        $check_query = tep_db_query("select orders_status_id from " . TABLE_ORDERS_STATUS . " where orders_status_name = 'Braintree [Transactions]' limit 1");
67
68
        if (tep_db_num_rows($check_query) < 1) {
69
          $status_query = tep_db_query("select max(orders_status_id) as status_id from " . TABLE_ORDERS_STATUS);
70
          $status = tep_db_fetch_array($status_query);
71
72
          $status_id = $status['status_id']+1;
73
74
          $languages = tep_get_languages();
75
76
          foreach ($languages as $lang) {
77
            tep_db_query("insert into " . TABLE_ORDERS_STATUS . " (orders_status_id, language_id, orders_status_name) values ('" . $status_id . "', '" . $lang['id'] . "', 'Braintree [Transactions]')");
78
          }
79
80
          $flags_query = tep_db_query("describe " . TABLE_ORDERS_STATUS . " public_flag");
81
          if (tep_db_num_rows($flags_query) == 1) {
82
            tep_db_query("update " . TABLE_ORDERS_STATUS . " set public_flag = 0 and downloads_flag = 0 where orders_status_id = '" . $status_id . "'");
83
          }
84
        } else {
85
          $check = tep_db_fetch_array($check_query);
86
87
          $status_id = $check['orders_status_id'];
88
        }
89
90
        $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_TRANSACTIONS_ORDER_STATUS_ID', $status_id);
91
      }
92
93
      if (!defined('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_SORT_ORDER')) {
94
        $cm = explode(';', MODULE_CONTENT_INSTALLED);
95
        $pos = array_search('account/cm_account_braintree_cards', $cm);
96
97
        if ($pos === false) {
98
          $cm[] = 'account/cm_account_braintree_cards';
99
100
          $this->saveParameter('MODULE_CONTENT_INSTALLED', implode(';', $cm));
101
        }
102
103
        $this->saveParameter('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_SORT_ORDER', '0', 'Sort Order', 'Sort order of display. Lowest is displayed first.');
104
      }
105
    }
106
107 View Code Duplication
    function migrate() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
      $migrated = false;
109
110
      foreach ( $this->getModules() as $module ) {
111
        if ( !defined('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_STATUS') ) {
112
          $this->saveParameter('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_STATUS', '');
113
114
          $class = 'OSCOM_Braintree_' . $module;
115
116
          if ( !class_exists($class) ) {
117
            $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
118
119
            include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
120
          }
121
122
          $m = new $class();
123
124
          if ( method_exists($m, 'canMigrate') && $m->canMigrate() ) {
125
            $m->migrate($this);
126
127
            if ( $migrated === false ) {
128
              $migrated = true;
129
            }
130
          }
131
        }
132
      }
133
134
      $this->deleteParameter('MODULE_CONTENT_ACCOUNT_BRAINTREE_CARDS_STATUS');
135
136
      return $migrated;
137
    }
138
139 View Code Duplication
    function getModules() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
      static $result;
141
142
      if ( !isset($result) ) {
143
        $result = array();
144
145
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/') ) {
146
          while ( $file = $dir->read() ) {
147
            if ( !in_array($file, array('.', '..')) && is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $file) && file_exists(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $file . '/' . $file . '.php') ) {
148
              $sort_order = $this->getModuleInfo($file, 'sort_order');
149
150
              if ( is_numeric($sort_order) ) {
151
                $counter = (int)$sort_order;
152
              } else {
153
                $counter = count($result);
154
              }
155
156
              while ( true ) {
157
                if ( isset($result[$counter]) ) {
158
                  $counter++;
159
160
                  continue;
161
                }
162
163
                $result[$counter] = $file;
164
165
                break;
166
              }
167
            }
168
          }
169
170
          ksort($result, SORT_NUMERIC);
171
        }
172
      }
173
174
      return $result;
175
    }
176
177 View Code Duplication
    function isInstalled($module) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
      if ( file_exists(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . basename($module) . '/' . basename($module) . '.php') ) {
179
        return defined('OSCOM_APP_PAYPAL_BRAINTREE_' . basename($module) . '_STATUS') && tep_not_null(constant('OSCOM_APP_PAYPAL_BRAINTREE_' . basename($module) . '_STATUS'));
180
      }
181
182
      return false;
183
    }
184
185 View Code Duplication
    function getModuleInfo($module, $info) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
      $class = 'OSCOM_Braintree_' . $module;
187
188
      if ( !class_exists($class) ) {
189
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
190
191
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
192
      }
193
194
      $m = new $class();
195
196
      return $m->{'_' . $info};
197
    }
198
199
    function hasApiCredentials($server) {
200
      $server = ($server == 'live') ? '' : 'SANDBOX_';
201
202
      $creds = array('OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'MERCHANT_ID',
203
                     'OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'PUBLIC_KEY',
204
                     'OSCOM_APP_PAYPAL_BRAINTREE_' . $server . 'PRIVATE_KEY');
205
206 View Code Duplication
      foreach ( $creds as $c ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
        if ( !defined($c) || (strlen(trim(constant($c))) < 1) ) {
208
          return false;
209
        }
210
      }
211
212
      return true;
213
    }
214
215 View Code Duplication
    function getApiCredentials($server, $type) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
      if ( ($server == 'live') && defined('OSCOM_APP_PAYPAL_BRAINTREE_LIVE_API_' . strtoupper($type)) ) {
217
        return constant('OSCOM_APP_PAYPAL_BRAINTREE_LIVE_API_' . strtoupper($type));
218
      } elseif ( defined('OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_API_' . strtoupper($type)) ) {
219
        return constant('OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_API_' . strtoupper($type));
220
      }
221
    }
222
223 View Code Duplication
    function getParameters($module) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
224
      $result = array();
225
226
      if ( $module == 'G' ) {
227
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/') ) {
228
          while ( $file = $dir->read() ) {
229
            if ( !is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/' . $file) && (substr($file, strrpos($file, '.')) == '.php') ) {
230
              $result[] = 'OSCOM_APP_PAYPAL_BRAINTREE_' . strtoupper(substr($file, 0, strrpos($file, '.')));
231
            }
232
          }
233
        }
234
      } else {
235
        if ( $dir = @dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/') ) {
236
          while ( $file = $dir->read() ) {
237
            if ( !is_dir(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $file) && (substr($file, strrpos($file, '.')) == '.php') ) {
238
              $result[] = 'OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_' . strtoupper(substr($file, 0, strrpos($file, '.')));
239
            }
240
          }
241
        }
242
      }
243
244
      return $result;
245
    }
246
247 View Code Duplication
    function getInputParameters($module) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248
      $result = array();
249
250
      if ( $module == 'G' ) {
251
        $cut = 'OSCOM_APP_PAYPAL_BRAINTREE_';
252
      } else {
253
        $cut = 'OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_';
254
      }
255
256
      $cut_length = strlen($cut);
257
258
      foreach ( $this->getParameters($module) as $key ) {
259
        $p = strtolower(substr($key, $cut_length));
260
261
        if ( $module == 'G' ) {
262
          $cfg_class = 'OSCOM_Braintree_Cfg_' . $p;
263
264
          if ( !class_exists($cfg_class) ) {
265
            $this->loadLanguageFile('cfg_params/' . $p . '.php');
266
267
            include(DIR_FS_CATALOG . 'includes/apps/braintree/cfg_params/' . $p . '.php');
268
          }
269
        } else {
270
          $cfg_class = 'OSCOM_Braintree_' . $module . '_Cfg_' . $p;
271
272
          if ( !class_exists($cfg_class) ) {
273
            $this->loadLanguageFile('modules/' . $module . '/cfg_params/' . $p . '.php');
274
275
            include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $p . '.php');
276
          }
277
        }
278
279
        $cfg = new $cfg_class();
280
281
        if ( !defined($key) ) {
282
          $this->saveParameter($key, $cfg->default, isset($cfg->title) ? $cfg->title : null, isset($cfg->description) ? $cfg->description : null, isset($cfg->set_func) ? $cfg->set_func : null);
283
        }
284
285
        if ( !isset($cfg->app_configured) || ($cfg->app_configured !== false) ) {
286
          if ( isset($cfg->sort_order) && is_numeric($cfg->sort_order) ) {
287
            $counter = (int)$cfg->sort_order;
288
          } else {
289
            $counter = count($result);
290
          }
291
292
          while ( true ) {
293
            if ( isset($result[$counter]) ) {
294
              $counter++;
295
296
              continue;
297
            }
298
299
            $set_field = $cfg->getSetField();
300
301
            if ( !empty($set_field) ) {
302
              $result[$counter] = $set_field;
303
            }
304
305
            break;
306
          }
307
        }
308
      }
309
310
      ksort($result, SORT_NUMERIC);
311
312
      return $result;
313
    }
314
315
    function makeApiCall($url, $parameters = null, $headers = null, $opts = null) {
316
      $server = parse_url($url);
317
318
      if ( !isset($server['port']) ) {
319
        $server['port'] = ($server['scheme'] == 'https') ? 443 : 80;
320
      }
321
322
      if ( !isset($server['path']) ) {
323
        $server['path'] = '/';
324
      }
325
326
      $curl = curl_init($server['scheme'] . '://' . $server['host'] . $server['path'] . (isset($server['query']) ? '?' . $server['query'] : ''));
327
      curl_setopt($curl, CURLOPT_PORT, $server['port']);
328
      curl_setopt($curl, CURLOPT_HEADER, false);
329
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
330
      curl_setopt($curl, CURLOPT_FORBID_REUSE, true);
331
      curl_setopt($curl, CURLOPT_FRESH_CONNECT, true);
332
      curl_setopt($curl, CURLOPT_ENCODING, ''); // disable gzip
333
334
      if ( isset($parameters) ) {
335
        curl_setopt($curl, CURLOPT_POST, true);
336
        curl_setopt($curl, CURLOPT_POSTFIELDS, $parameters);
337
      }
338
339 View Code Duplication
      if ( isset($headers) && is_array($headers) && !empty($headers) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
341
      }
342
343 View Code Duplication
      if ( isset($server['user']) && isset($server['pass']) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
344
        curl_setopt($curl, CURLOPT_USERPWD, $server['user'] . ':' . $server['pass']);
345
      }
346
347
      if ( defined('OSCOM_APP_PAYPAL_BRAINTREE_VERIFY_SSL') && (OSCOM_APP_PAYPAL_BRAINTREE_VERIFY_SSL == '1') ) {
348
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
349
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
350
351
        if ( file_exists(DIR_FS_CATALOG . 'includes/cacert.pem') ) {
352
          curl_setopt($curl, CURLOPT_CAINFO, DIR_FS_CATALOG . 'includes/cacert.pem');
353
        }
354
      } else {
355
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
356
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
357
      }
358
359 View Code Duplication
      if (substr($server['host'], -10) == 'paypal.com') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
        $ssl_version = 0;
361
362
        if ( defined('OSCOM_APP_PAYPAL_BRAINTREE_SSL_VERSION') && (OSCOM_APP_PAYPAL_BRAINTREE_SSL_VERSION == '1') ) {
363
          $ssl_version = 6;
364
        }
365
366
        if (isset($opts['sslVersion']) && is_int($opts['sslVersion'])) {
367
          $ssl_version = $opts['sslVersion'];
368
        }
369
370
        if ($ssl_version !== 0) {
371
          curl_setopt($curl, CURLOPT_SSLVERSION, $ssl_version);
372
        }
373
      }
374
375 View Code Duplication
      if ( defined('OSCOM_APP_PAYPAL_BRAINTREE_PROXY') && tep_not_null(OSCOM_APP_PAYPAL_BRAINTREE_PROXY) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
376
        curl_setopt($curl, CURLOPT_HTTPPROXYTUNNEL, true);
377
        curl_setopt($curl, CURLOPT_PROXY, OSCOM_APP_PAYPAL_BRAINTREE_PROXY);
378
      }
379
380
      $result = curl_exec($curl);
381
382 View Code Duplication
      if (isset($opts['returnFull']) && ($opts['returnFull'] === true)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
383
        $result = array(
384
          'response' => $result,
385
          'error' => curl_error($curl),
386
          'info' => curl_getinfo($curl)
387
        );
388
      }
389
390
      curl_close($curl);
391
392
      return $result;
393
    }
394
395 View Code Duplication
    function drawButton($title = null, $link = null, $type = null, $params = null, $force_css = false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
396
      $colours = array('success' => '#1cb841',
397
                       'error' => '#ca3c3c',
398
                       'warning' => '#ebaa16',
399
                       'info' => '#42B8DD',
400
                       'primary' => '#0078E7');
401
402
      if ( !isset($type) || !in_array($type, array_keys($colours)) ) {
403
        $type = 'info';
404
      }
405
406
      $css = 'font-size:14px;color:#fff;padding:8px 16px;border:0;border-radius:4px;text-shadow:0 1px 1px rgba(0, 0, 0, 0.2);text-decoration:none;display:inline-block;cursor:pointer;white-space:nowrap;vertical-align:baseline;text-align:center;background-color:' . $colours[$type] . ';';
407
408
      $button = '';
409
410
      if ( isset($link) ) {
411
        $button .= '<a href="' . $link . '" class="bt-button';
412
413
        if ( isset($type) ) {
414
          $button .= ' bt-button-' . $type;
415
        }
416
417
        $button .= '"';
418
419
        if ( isset($params) ) {
420
          $button .= ' ' . $params;
421
        }
422
423
        if ( $force_css == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
424
          $button .= ' style="' . $css . '"';
425
        }
426
427
        $button .= '>' . $title . '</a>';
428
      } else {
429
        $button .= '<button type="submit" class="bt-button';
430
431
        if ( isset($type) ) {
432
          $button .= ' bt-button-' . $type;
433
        }
434
435
        $button .= '"';
436
437
        if ( isset($params) ) {
438
          $button .= ' ' . $params;
439
        }
440
441
        if ( $force_css == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
442
          $button .= ' style="' . $css . '"';
443
        }
444
445
        $button .= '>' . $title . '</button>';
446
      }
447
448
      return $button;
449
    }
450
451 View Code Duplication
    function createRandomValue($length, $type = 'mixed') {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
      if ( ($type != 'mixed') && ($type != 'chars') && ($type != 'digits')) $type = 'mixed';
453
454
      $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
455
      $digits = '0123456789';
456
457
      $base = '';
458
459
      if ( ($type == 'mixed') || ($type == 'chars') ) {
460
        $base .= $chars;
461
      }
462
463
      if ( ($type == 'mixed') || ($type == 'digits') ) {
464
        $base .= $digits;
465
      }
466
467
      $value = '';
468
469
      if ( !class_exists('PasswordHash') && file_exists(DIR_FS_CATALOG . 'includes/classes/passwordhash.php') ) {
470
        include(DIR_FS_CATALOG . 'includes/classes/passwordhash.php');
471
472
        $hasher = new PasswordHash(10, true);
473
474
        do {
475
          $random = base64_encode($hasher->get_random_bytes($length));
476
477
          for ($i = 0, $n = strlen($random); $i < $n; $i++) {
478
            $char = substr($random, $i, 1);
479
480
            if ( strpos($base, $char) !== false ) {
481
              $value .= $char;
482
            }
483
          }
484
        } while ( strlen($value) < $length );
485
486
        if ( strlen($value) > $length ) {
487
          $value = substr($value, 0, $length);
488
        }
489
490
        return $value;
491
      }
492
493
// fallback for v2.3.1
494
      while ( strlen($value) < $length ) {
495
        if ($type == 'digits') {
496
          $char = tep_rand(0,9);
497
        } else {
498
          $char = chr(tep_rand(0,255));
499
        }
500
501
        if ( $type == 'mixed' ) {
502
          if (preg_match('/^[a-z0-9]$/i', $char)) $value .= $char;
503
        } elseif ($type == 'chars') {
504
          if (preg_match('/^[a-z]$/i', $char)) $value .= $char;
505
        } elseif ($type == 'digits') {
506
          if (preg_match('/^[0-9]$/i', $char)) $value .= $char;
507
        }
508
      }
509
510
      return $value;
511
    }
512
513 View Code Duplication
    function saveParameter($key, $value, $title = null, $description = null, $set_func = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
514
      if ( !defined($key) ) {
515
        if ( !isset($title) ) {
516
          $title = 'Braintree App Parameter';
517
        }
518
519
        if ( !isset($description) ) {
520
          $description = 'A parameter for the Braintree Application.';
521
        }
522
523
        tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('" . tep_db_input($title) . "', '" . tep_db_input($key) . "', '" . tep_db_input($value) . "', '" . tep_db_input($description) . "', '6', '0', now())");
524
525
        if ( isset($set_func) ) {
526
          tep_db_query("update " . TABLE_CONFIGURATION . " set set_function = '" . tep_db_input($set_func) . "' where configuration_key = '" . tep_db_input($key) . "'");
527
        }
528
529
        define($key, $value);
530
      } else {
531
        tep_db_query("update " . TABLE_CONFIGURATION . " set configuration_value = '" . tep_db_input($value) . "' where configuration_key = '" . tep_db_input($key) . "'");
532
      }
533
    }
534
535
    function deleteParameter($key) {
536
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key = '" . tep_db_input($key) . "'");
537
    }
538
539
    function setupCredentials($server = null) {
540
      $status = ((isset($server) && ($server === 'live')) || (!isset($server) && (OSCOM_APP_PAYPAL_BRAINTREE_CC_STATUS === '1'))) ? '1' : '0';
541
542
      Braintree_Configuration::environment($status === '1' ? 'production' : 'sandbox');
543
      Braintree_Configuration::merchantId($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_MERCHANT_ID : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_MERCHANT_ID);
544
      Braintree_Configuration::publicKey($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_PUBLIC_KEY : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_PUBLIC_KEY);
545
      Braintree_Configuration::privateKey($status === '1' ? OSCOM_APP_PAYPAL_BRAINTREE_PRIVATE_KEY : OSCOM_APP_PAYPAL_BRAINTREE_SANDBOX_PRIVATE_KEY);
546
547
      if (defined('OSCOM_APP_PAYPAL_BRAINTREE_SSL_VERSION') && (OSCOM_APP_PAYPAL_BRAINTREE_SSL_VERSION == '1')) {
548
        Braintree_Configuration::sslVersion(6);
549
      }
550
551
      if (defined('OSCOM_APP_PAYPAL_BRAINTREE_PROXY') && tep_not_null(OSCOM_APP_PAYPAL_BRAINTREE_PROXY)) {
552
        $url = parse_url(OSCOM_APP_PAYPAL_BRAINTREE_PROXY);
553
554
        Braintree_Configuration::proxyHost($url['host']);
555
556
        if (isset($url['port'])) {
557
          Braintree_Configuration::proxyPort($url['port']);
558
        }
559
      }
560
    }
561
562 View Code Duplication
    function formatCurrencyRaw($total, $currency_code = null, $currency_value = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
563
      global $currencies, $currency;
564
565
      if ( !isset($currency_code) ) {
566
        $currency_code = tep_session_is_registered('currency') ? $currency : DEFAULT_CURRENCY;
567
      }
568
569
      if ( !isset($currency_value) || !is_numeric($currency_value) ) {
570
        $currency_value = $currencies->currencies[$currency_code]['value'];
571
      }
572
573
      return number_format(tep_round($total * $currency_value, $currencies->currencies[$currency_code]['decimal_places']), $currencies->currencies[$currency_code]['decimal_places'], '.', '');
574
    }
575
576
    function getCode() {
577
      return $this->_code;
578
    }
579
580
    function getTitle() {
581
      return $this->_title;
582
    }
583
584 View Code Duplication
    function getVersion() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
585
      if ( !isset($this->_version) ) {
586
        $version = trim(file_get_contents(DIR_FS_CATALOG . 'includes/apps/braintree/version.txt'));
587
588
        if ( is_numeric($version) ) {
589
          $this->_version = $version;
590
        } else {
591
          trigger_error('OSCOM APP [BRAINTREE]: Could not read App version number.');
592
        }
593
      }
594
595
      return $this->_version;
596
    }
597
598
    function getApiVersion() {
599
      return $this->_api_version;
600
    }
601
602
    function getIdentifier() {
603
      return $this->_identifier;
604
    }
605
606
    function hasAlert() {
607
      return tep_session_is_registered('OSCOM_Braintree_Alerts');
608
    }
609
610 View Code Duplication
    function addAlert($message, $type) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
611
      global $OSCOM_Braintree_Alerts;
612
613
      if ( in_array($type, array('error', 'warning', 'success')) ) {
614
        if ( !tep_session_is_registered('OSCOM_Braintree_Alerts') ) {
615
          $OSCOM_Braintree_Alerts = array();
616
          tep_session_register('OSCOM_Braintree_Alerts');
617
        }
618
619
        $OSCOM_Braintree_Alerts[$type][] = $message;
620
      }
621
    }
622
623 View Code Duplication
    function getAlerts() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
624
      global $OSCOM_Braintree_Alerts;
625
626
      $output = '';
627
628
      if ( tep_session_is_registered('OSCOM_Braintree_Alerts') && !empty($OSCOM_Braintree_Alerts) ) {
629
        $result = array();
630
631
        foreach ( $OSCOM_Braintree_Alerts as $type => $messages ) {
632
          if ( in_array($type, array('error', 'warning', 'success')) ) {
633
            $m = '<ul class="bt-alerts-' . $type . '">';
634
635
            foreach ( $messages as $message ) {
636
              $m .= '<li>' . tep_output_string_protected($message) . '</li>';
637
            }
638
639
            $m .= '</ul>';
640
641
            $result[] = $m;
642
          }
643
        }
644
645
        if ( !empty($result) ) {
646
          $output .= '<div class="bt-alerts">' . implode("\n", $result) . '</div>';
647
        }
648
      }
649
650
      tep_session_unregister('OSCOM_Braintree_Alerts');
651
652
      return $output;
653
    }
654
655 View Code Duplication
    function install($module) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
656
      $cut_length = strlen('OSCOM_APP_PAYPAL_BRAINTREE_' . $module . '_');
657
658
      foreach ( $this->getParameters($module) as $key ) {
659
        $p = strtolower(substr($key, $cut_length));
660
661
        $cfg_class = 'OSCOM_Braintree_' . $module . '_Cfg_' . $p;
662
663
        if ( !class_exists($cfg_class) ) {
664
          $this->loadLanguageFile('modules/' . $module . '/cfg_params/' . $p . '.php');
665
666
          include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/cfg_params/' . $p . '.php');
667
        }
668
669
        $cfg = new $cfg_class();
670
671
        $this->saveParameter($key, $cfg->default, isset($cfg->title) ? $cfg->title : null, isset($cfg->description) ? $cfg->description : null, isset($cfg->set_func) ? $cfg->set_func : null);
672
      }
673
674
      $m_class = 'OSCOM_Braintree_' . $module;
675
676
      if ( !class_exists($m_class) ) {
677
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
678
679
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
680
      }
681
682
      $m = new $m_class();
683
684
      if ( method_exists($m, 'install') ) {
685
        $m->install($this);
686
      }
687
    }
688
689 View Code Duplication
    function uninstall($module) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
690
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key like 'OSCOM_APP_PAYPAL_BRAINTREE_" . tep_db_input($module) . "_%'");
691
692
      $m_class = 'OSCOM_Braintree_' . $module;
693
694
      if ( !class_exists($m_class) ) {
695
        $this->loadLanguageFile('modules/' . $module . '/' . $module . '.php');
696
697
        include(DIR_FS_CATALOG . 'includes/apps/braintree/modules/' . $module . '/' . $module . '.php');
698
      }
699
700
      $m = new $m_class();
701
702
      if ( method_exists($m, 'uninstall') ) {
703
        $m->uninstall($this);
704
      }
705
    }
706
707
    function logUpdate($message, $version) {
708 View Code Duplication
      if ( is_writable(DIR_FS_CATALOG . 'includes/apps/braintree/work') ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
709
        file_put_contents(DIR_FS_CATALOG . 'includes/apps/braintree/work/update_log-' . $version . '.php', '[' . date('d-M-Y H:i:s') . '] ' . $message . "\n", FILE_APPEND);
710
      }
711
    }
712
713 View Code Duplication
    public function loadLanguageFile($filename, $lang = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
714
      global $language;
715
716
      $lang = isset($lang) ? basename($lang) : basename($language);
717
718
      if ( $lang != 'english' ) {
719
        $this->loadLanguageFile($filename, 'english');
720
      }
721
722
      $pathname = DIR_FS_CATALOG . 'includes/apps/braintree/languages/' . $lang . '/' . $filename;
723
724
      if ( file_exists($pathname) ) {
725
        $contents = file($pathname);
726
727
        $ini_array = array();
728
729
        foreach ( $contents as $line ) {
730
          $line = trim($line);
731
732
          if ( !empty($line) && (substr($line, 0, 1) != '#') ) {
733
            $delimiter = strpos($line, '=');
734
735
            if ( ($delimiter !== false) && (preg_match('/^[A-Za-z0-9_-]/', substr($line, 0, $delimiter)) === 1) && (substr_count(substr($line, 0, $delimiter), ' ') == 1) ) {
736
              $key = trim(substr($line, 0, $delimiter));
737
              $value = trim(substr($line, $delimiter + 1));
738
739
              $ini_array[$key] = $value;
740
            } elseif ( isset($key) ) {
741
              $ini_array[$key] .= "\n" . $line;
742
            }
743
          }
744
        }
745
746
        unset($contents);
747
748
        $this->_definitions = array_merge($this->_definitions, $ini_array);
749
750
        unset($ini_array);
751
      }
752
    }
753
754 View Code Duplication
    function getDef($key, $values = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
755
      $def = isset($this->_definitions[$key]) ? $this->_definitions[$key] : $key;
756
757
      if ( is_array($values) ) {
758
        $keys = array_keys($values);
759
760
        foreach ( $keys as &$k ) {
761
          $k = ':' . $k;
762
        }
763
764
        $def = str_replace($keys, array_values($values), $def);
765
      }
766
767
      return $def;
768
    }
769
770 View Code Duplication
    function getDirectoryContents($base, &$result = array()) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
771
      foreach ( scandir($base) as $file ) {
772
        if ( ($file == '.') || ($file == '..') ) {
773
          continue;
774
        }
775
776
        $pathname = $base . '/' . $file;
777
778
        if ( is_dir($pathname) ) {
779
          $this->getDirectoryContents($pathname, $result);
780
        } else {
781
          $result[] = str_replace('\\', '/', $pathname); // Unix style directory separator "/"
782
        }
783
      }
784
785
      return $result;
786
    }
787
788 View Code Duplication
    function isWritable($location) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
789
      if ( !file_exists($location) ) {
790
        while ( true ) {
791
          $location = dirname($location);
792
793
          if ( file_exists($location) ) {
794
            break;
795
          }
796
        }
797
      }
798
799
      return is_writable($location);
800
    }
801
802 View Code Duplication
    function rmdir($dir) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
803
      foreach ( scandir($dir) as $file ) {
804
        if ( !in_array($file, array('.', '..')) ) {
805
          if ( is_dir($dir . '/' . $file) ) {
806
            $this->rmdir($dir . '/' . $file);
807
          } else {
808
            unlink($dir . '/' . $file);
809
          }
810
        }
811
      }
812
813
      return rmdir($dir);
814
    }
815
816
    function displayPath($pathname) {
817
      if ( DIRECTORY_SEPARATOR == '/' ) {
818
        return $pathname;
819
      }
820
821
      return str_replace('/', DIRECTORY_SEPARATOR, $pathname);
822
    }
823
// OSCOM v2.2rc2a compatibility
824 View Code Duplication
    function getIpAddress() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
825
      if ( function_exists('tep_get_ip_address') ) {
826
        return tep_get_ip_address();
827
      }
828
      global $HTTP_SERVER_VARS;
829
      $ip_address = null;
830
      $ip_addresses = array();
831
      if (isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']) && !empty($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])) {
832
        foreach ( array_reverse(explode(',', $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'])) as $x_ip ) {
833
          $x_ip = trim($x_ip);
834
          if ($this->isValidIpAddress($x_ip)) {
835
            $ip_addresses[] = $x_ip;
836
          }
837
        }
838
      }
839
      if (isset($HTTP_SERVER_VARS['HTTP_CLIENT_IP']) && !empty($HTTP_SERVER_VARS['HTTP_CLIENT_IP'])) {
840
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_CLIENT_IP'];
841
      }
842
      if (isset($HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP']) && !empty($HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP'])) {
843
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_X_CLUSTER_CLIENT_IP'];
844
      }
845
      if (isset($HTTP_SERVER_VARS['HTTP_PROXY_USER']) && !empty($HTTP_SERVER_VARS['HTTP_PROXY_USER'])) {
846
        $ip_addresses[] = $HTTP_SERVER_VARS['HTTP_PROXY_USER'];
847
      }
848
      $ip_addresses[] = $HTTP_SERVER_VARS['REMOTE_ADDR'];
849
      foreach ( $ip_addresses as $ip ) {
850
        if (!empty($ip) && $this->isValidIpAddress($ip)) {
851
          $ip_address = $ip;
852
          break;
853
        }
854
      }
855
      return $ip_address;
856
    }
857
// OSCOM v2.2rc2a compatibility
858 View Code Duplication
    function isValidIpAddress($ip_address) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
859
      if ( function_exists('tep_validate_ip_address') ) {
860
        return tep_validate_ip_address($ip_address);
861
      }
862
      if (function_exists('filter_var') && defined('FILTER_VALIDATE_IP')) {
863
        return filter_var($ip_address, FILTER_VALIDATE_IP, array('flags' => FILTER_FLAG_IPV4));
864
      }
865
      if (preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $ip_address)) {
866
        $parts = explode('.', $ip_address);
867
        foreach ($parts as $ip_parts) {
868
          if ( (intval($ip_parts) > 255) || (intval($ip_parts) < 0) ) {
869
            return false; // number is not within 0-255
870
          }
871
        }
872
        return true;
873
      }
874
      return false;
875
    }
876
  }
877
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
878