Tried to fix installer a bit + added missing language string.
[mailer.git] / inc / libs / wernis_functions.php
1 <?php
2 /************************************************************************
3  * Mailer v0.2.1-FINAL                                Start: 10/19/2003 *
4  * ===================                          Last change: 08/12/2004 *
5  *                                                                      *
6  * -------------------------------------------------------------------- *
7  * File              : what-points.php                                  *
8  * -------------------------------------------------------------------- *
9  * Short description : All your collected points...                     *
10  * -------------------------------------------------------------------- *
11  * Kurzbeschreibung  : Alle Ihrer gesammelten Punkte                    *
12  * -------------------------------------------------------------------- *
13  * $Revision::                                                        $ *
14  * $Date::                                                            $ *
15  * $Tag:: 0.2.1-FINAL                                                 $ *
16  * $Author::                                                          $ *
17  * -------------------------------------------------------------------- *
18  * Copyright (c) 2003 - 2009 by Roland Haeder                           *
19  * Copyright (c) 2009 - 2015 by Mailer Developer Team                   *
20  * For more information visit: http://mxchange.org                      *
21  *                                                                      *
22  * This program is free software; you can redistribute it and/or modify *
23  * it under the terms of the GNU General Public License as published by *
24  * the Free Software Foundation; either version 2 of the License, or    *
25  * (at your option) any later version.                                  *
26  *                                                                      *
27  * This program is distributed in the hope that it will be useful,      *
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
30  * GNU General Public License for more details.                         *
31  *                                                                      *
32  * You should have received a copy of the GNU General Public License    *
33  * along with this program; if not, write to the Free Software          *
34  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
35  * MA  02110-1301  USA                                                  *
36  ************************************************************************/
37
38 // Some security stuff...
39 if (!defined('__SECURITY')) {
40         die();
41 } // END - if
42
43 // Sets a status message and code
44 function setWernisStatusMessage ($message, $status) {
45         $GLOBALS['wernis_data']['message'] = $message;
46         $GLOBALS['wernis_data']['status']  = $status;
47 }
48
49 // Get the status message
50 function getWernisErrorMessage () {
51         if (isset($GLOBALS['wernis_data']['message'])) {
52                 // Use raw message
53                 return $GLOBALS['wernis_data']['message'];
54         } elseif (isset($GLOBALS['wernis_data']['status'])) {
55                 // Fall-back to status
56                 return '{%message,WERNIS_ERROR_STATUS=' . $GLOBALS['wernis_data']['status'] . '%}';
57         } else {
58                 // Something bad happend
59                 return '{--WERNIS_UNKNOWN_ERROR--}';
60         }
61 }
62
63 // Get the status code
64 function getWernisErrorCode () {
65         if (isset($GLOBALS['wernis_data']['status'])) {
66                 // Use raw message
67                 return $GLOBALS['wernis_data']['status'];
68         } else {
69                 // Something bad happend
70                 return '{--WERNIS_UNKNOWN_ERROR--}';
71         }
72 }
73
74 // Sends out a request to the API and returns it's result
75 function sendWernisApiRequest ($scriptName, $requestData = array()) {
76         // Debug call
77         //* DEBUG */ reportBug(__FUNCTION__, __LINE__, 'scriptName=' . $scriptName . ',requestData=<pre>' . print_r($requestData, TRUE) . '</pre>');
78
79         // Is the requestData an array?
80         if (!is_array($requestData)) {
81                 // Then abort here!
82                 return array(
83                         'status'  => 'failed_general',
84                         'message' => '{--WERNIS_API_REQUEST_DATA_INVALID--}'
85                 );
86         } // END - if
87
88         // Is the API id and MD5 hash there?
89         if ((getWernisApiId() == '') || (getWernisApiMd5() == '')) {
90                 // Abort here...
91                 return array(
92                         'status'  => 'failed_general',
93                         'message' => '{--WERNIS_API_REQUEST_DATA_MISSING--}'
94                 );
95         } // END - if
96
97         // Add more request data
98         $requestData['api_id']  = getWernisApiId();
99         $requestData['api_key'] = getWernisApiMd5();
100
101         // Is a purpose there?
102         if (!empty($requestData['purpose'])) {
103                 // Eval the purpose
104                 eval('$purpose = "' . doFinalCompilation($requestData['purpose'], FALSE) . '";');
105
106                 // Prepare the purpose, it needs encoding
107                 $requestData['purpose'] = encodeString($purpose);
108         } // END - if
109
110         // Construct the request string
111         $requestString = getWernisApiUrl() . $scriptName;
112
113         // Get the raw response from the lower function
114         $response = sendHttpPostRequest($requestString, $requestData);
115
116         // Check the response header if all is fine
117         if (!isHttpStatusOkay($response[0])) {
118                 // Something bad happend... :(
119                 return array(
120                         'status'  => 'request_error',
121                         'message' => '{%message,WERNIS_API_REQUEST_ERROR=' . $response[0] . '%}'
122                 );
123         } // END - if
124
125         // All (maybe) fine so remove the response header from server
126         $responseLine = '*INVALID*';
127         for ($idx = (count($response) - 1); $idx > 1; $idx--) {
128                 $line = trim($response[$idx]);
129                 if (!empty($line)) {
130                         $responseLine = $line;
131                         break;
132                 } // END - if
133         } // END - for
134
135         // Is the response leaded by a & symbol?
136         if (substr($responseLine, 0, 1) != '&') {
137                 // Something badly happened on server-side
138                 return array(
139                         'status'  => 'request_problem',
140                         'message' => sprintf(getMessage('WERNIS_API_REQUEST_PROBLEM'), $response[0], secureString($responseLine))
141                 );
142         } // END - if
143
144         // Remove the leading & (which can be used in Flash)
145         $responseLine = substr($responseLine, 1);
146
147         // Bring back the response
148         $data = explode('=', $responseLine);
149
150         // Default return array (should not stay empty)
151         $return = array();
152
153         // We use only the first two entries (which shall be fine)
154         if ($data[0] === 'error') {
155                 // The request has failed...
156                 $status = $data[1];
157                 $extraData = '';
158
159                 // Explode status code
160                 $exploded = explode(':', $status);
161
162                 // More extra data found?
163                 if (count($exploded) > 1) {
164                         // Then set all
165                         $status    = $exploded[0];
166                         $extraData = $exploded[1];
167                 } // END - if
168
169                 switch ($status) {
170                         case '404': // Invalid API id
171                         case 'AUTH': // Authorization has failed
172                                 $return = array(
173                                         'status'  => 'auth_failed',
174                                         'message' => '{--WERNIS_API_REQUEST_FAILED_AUTH--}'
175                                 );
176                                 break;
177
178                         case 'LOCKED': // User account is locked!
179                         case 'PASS': // Bad passphrase entered
180                         case 'USER': // Missing account or invalid password
181                                 $return = array(
182                                         'status'  => 'user_failed',
183                                         'message' => '{--WERNIS_API_REQUEST_FAILED_USER--}'
184                                 );
185                                 break;
186
187                         case 'OWN': // Transfer to own account
188                                 $return = array(
189                                         'status'  => 'own_failed',
190                                         'message' => '{--WERNIS_API_REQUEST_FAILED_OWN--}'
191                                 );
192                                 break;
193
194                         case 'AMOUNT': // Amount is depleted
195                                 $return = array(
196                                         'status'  => 'amount_failed',
197                                         'message' => '{--WERNIS_API_REQUEST_FAILED_AMOUNT--}'
198                                 );
199                                 break;
200
201                         case 'AMOUNT-SEND': // API amount is depleted
202                                 $return = array(
203                                         'status'  => 'api_amount_failed',
204                                         'message' => '{--WERNIS_API_REQUEST_FAILED_API_AMOUNT--}'
205                                 );
206                                 break;
207
208                         case 'AUTH-STATUS': // Unexpected auth status
209                                 // Switch on extra data
210                                 switch ($extraData) {
211                                         case 'ACCEPTED':
212                                                 $return = array(
213                                                         'status'  => 'api_auth_status_accepted',
214                                                         'message' => '{--WERNIS_API_REQUEST_FAILED_AUTH_STATUS_ACCEPTED--}'
215                                                 );
216                                                 break;
217
218                                         case 'REJECTED':
219                                                 $return = array(
220                                                         'status'  => 'api_auth_status_rejected',
221                                                         'message' => '{--WERNIS_API_REQUEST_FAILED_AUTH_STATUS_REJECTED--}'
222                                                 );
223                                                 break;
224
225                                         case 'UNKNOWN':
226                                                 $return = array(
227                                                         'status'  => 'api_auth_status_unknown',
228                                                         'message' => '{--WERNIS_API_REQUEST_FAILED_AUTH_STATUS_UNKNOWN--}'
229                                                 );
230                                                 break;
231
232                                         default: // Unknown
233                                                 $return = array(
234                                                         'status'  => 'api_auth_status_failed',
235                                                         'message' => getMaskedMessage('WERNIS_API_REQUEST_FAILED_AUTH_STATUS', $extraData)
236                                                 );
237                                                 break;
238                                 } // END - switch
239                                 break;
240
241                         default: // Unknown error (maybe new?)
242                                 logDebugMessage(__FUNCTION__, __LINE__, sprintf('Unknown error %s from WDS66 API received.', $data[1]));
243                                 $return = array(
244                                         'status'  => 'request_failed',
245                                         'message' => '{%message,WERNIS_API_REQUEST_FAILED=' . $data[1] . '%}'
246                                 );
247                                 break;
248                 } // END - switch
249         } else {
250                 // All fine, then analyze API response
251                 $return = convertApiResponseToArray($responseLine, '&', '=');
252
253                 // Nothing is fine now
254                 $return['status']  = 'generic_failed';
255                 $return['message'] = '--WERNIS_API_REQUEST_FAILED_GENERIC--}';
256
257                 // Are 'encrypted', 'key' and 'iv' set?
258                 //* DEBUG-DIE */ die(__FUNCTION__ . ':return=<pre>' . print_r($return, TRUE) . '</pre>');
259                 if ((isset($return['encrypted'])) && (isset($return['key'])) && (isset($return['iv']))) {
260                         // Fully decode it (URL-encoded BASE64)
261                         $decoded = decodeString($return['encrypted']);
262                         $iv      = decodeString($return['iv']);
263
264                         // Generate decryption key
265                         $decryptionKey = generateWernisDecryptionKey($return['key']);
266
267                         // Decrypt string
268                         $decrypted = decrytStringByCipher($decoded, getWernisEncryptionAlgorithm(), getWernisEncryptionMode(), $decryptionKey, $iv);
269                         //* DEBUG-DIE */ die('key="' . $return['key'] . '"<br />decryptionKey="' . $decryptionKey . '"<br />decoded="' . $decoded . '"<br />decrypted="' . $decrypted . '"');
270
271                         // First char must be an &
272                         assert(substr($decrypted, 0, 1) == '&');
273
274                         // Now the string needs to be turned into an array, first explode all &
275                         $elements = explode('&', $decrypted);
276
277                         // And remove first element
278                         array_shift($elements);
279                         //* DEBUG-DIE */ die('elements=<pre>' . print_r($elements, TRUE) . '</pre>');
280
281                         // Now "walk" all ements
282                         foreach ($elements as $idx => $element) {
283                                 // Explode element
284                                 $keyValue = explode('=', $element);
285
286                                 // Make sure it is valid
287                                 assert(count($keyValue) == 2);
288
289                                 // Now handle all over
290                                 $return[$keyValue[0]] = $keyValue[1];
291                         } // END - foreach
292
293                         // Remove encryption stuff
294                         unset($return['encrypted'], $return['key'], $return['iv']);
295                 } // END - if
296
297                 // All fine ...
298                 $return['status']  = 'OK';
299                 $return['message'] = NULL;
300         }
301
302         // Return the result
303         //* DEBUG-DIE */ die(__FUNCTION__ . ':return=<pre>' . print_r($return, TRUE) . '</pre>');
304         return $return;
305 }
306
307 // Tests the function by calling balance.php on the API
308 function doAdminTestWernisApi () {
309         // Only as admin
310         assert(isAdmin());
311
312         // Result is always failed
313         $result = FALSE;
314
315         // Prepare the request data
316         $requestData = array(
317                 't_uid' => getWernisRefid(),
318                 't_md5' => getWernisPassMd5()
319         );
320
321         // Return the result from the lower functions
322         $return = sendWernisApiRequest('balance.php', $requestData);
323
324         // Did it went smoothly?
325         if (isHttpResponseStatusOkay($return)) {
326                 // All fine!
327                 $result = TRUE;
328         } else {
329                 // Status failure text
330                 setWernisStatusMessage($return['message'], $return['status']);
331         }
332
333         // Return result
334         return $result;
335 }
336
337 // Widthdraw this amount
338 function executeWernisApiWithdraw ($wdsId, $userMd5, $amount) {
339         // Is the sponsor extension installed?
340         if (!isWernisWithdrawActive()) {
341                 if (!isExtensionActive('sponsor')) {
342                         // No, abort here
343                         return FALSE;
344                 } elseif (!isSponsor()) {
345                         // No sponsor, not allowed to withdraw!
346                         return FALSE;
347                 }
348         } // END - if
349
350         // Default is failed attempt
351         $result = FALSE;
352
353         // Prepare the request data
354         $requestData = array(
355                 'sub_request' => 'receive',
356                 't_uid'       => bigintval($wdsId),
357                 't_md5'       => $userMd5,
358                 'r_uid'       => getWernisRefid(),
359                 'amount'      => bigintval($amount),
360                 'purpose'     => getMaskedMessage('WERNIS_API_PURPOSE_WITHDRAW', getMemberId())
361         );
362
363         // Return the result from the lower functions
364         $return = sendWernisApiRequest('book.php', $requestData);
365
366         // Did it went smoothly?
367         if (isHttpResponseStatusOkay($return)) {
368                 // All fine!
369                 $result = TRUE;
370
371                 // Log the transfer
372                 logWernisTransfer($wdsId, $amount, 'WITHDRAW');
373         } else {
374                 // Status failure text
375                 setWernisStatusMessage($return['message'], $return['status']);
376
377                 // Log the transfer
378                 logWernisTransfer($wdsId, $amount, 'FAILED', $return['message'], $return['status']);
379         }
380
381         // Return result
382         return $result;
383 }
384
385 // Payout this amount
386 function executeWernisApiPayout ($wdsId, $amount) {
387         // Default is failed attempt
388         $result = FALSE;
389
390         // Prepare the request data
391         $requestData = array(
392                 'sub_request' => 'send',
393                 't_uid'       => getWernisRefid(),
394                 't_md5'       => getWernisPassMd5(),
395                 'r_uid'       => bigintval($wdsId),
396                 'amount'      => bigintval($amount),
397                 'purpose'     => getMaskedMessage('WERNIS_API_PURPOSE_PAYOUT', getMemberId())
398         );
399
400         // Return the result from the lower functions
401         $return = sendWernisApiRequest('book.php', $requestData);
402
403         if (isHttpResponseStatusOkay($return)) {
404                 // All fine!
405                 $result = TRUE;
406
407                 // Log the transfer
408                 logWernisTransfer($wdsId, $amount, 'PAYOUT');
409         } else {
410                 // Status failure text
411                 setWernisStatusMessage($return['message'], $return['status']);
412
413                 // Log the transfer
414                 logWernisTransfer($wdsId, $amount, 'FAILED', $return['message'], $return['status']);
415         }
416
417         // Return result
418         return $result;
419 }
420
421 // Execute auth.php request
422 function executeWernisApiAuth ($wernisId, $wernisPassword) {
423         // Prepare request data
424         $requestData = array(
425                 't_uid'       => bigintval($wernisId),
426                 't_md5'       => hashSha256($wernisPassword),
427         );
428
429         // Call auth.php
430         $return = sendWernisApiRequest('auth.php', $requestData);
431
432         // Return full array
433         return $return;
434 }
435
436 // Execute get.php reguest with given auth data (not all are used)
437 function executeWernisApiGet ($authData, $subRequest, $fields) {
438         // It must be an array
439         assert(is_array($authData));
440
441         // Check required array elements
442         assert(isset($authData['wernis_userid']));
443         assert(isset($authData['api_auth_key']));
444         assert(isset($authData['api_redirect_challenge']));
445
446         // Then create request array
447         $requestData = array(
448                 'sub_request' => $subRequest,
449                 'fields'      => $fields,
450                 't_uid'       => bigintval($authData['wernis_userid']),
451                 't_md5'       => getWernisPassMd5(),
452                 'auth_key'    => $authData['api_auth_key'],
453                 'challenge'   => $authData['api_redirect_challenge']
454         );
455
456         // Call get.php
457         $return = sendWernisApiRequest('get.php', $requestData);
458
459         // Return full array
460         return $return;
461 }
462
463 // Translate auth status
464 function translateWernisAuthStatu ($status) {
465         return '{%message,WERNIS_AUTH_STATUS_' . strtoupper($status) . '%}';
466 }
467
468 // Translate the status IN/OUT
469 function translateWernisTransferStatus ($status) {
470         // Default status is unknown
471         $return = '{%message,WERNIS_TRANSFER_STATUS_UNKNWOWN=' . $status . '%}';
472
473         // Construct message id
474         $messageId = 'WERNIS_TRANSFER_STATUS_' . $status;
475
476         // Is it there?
477         if (isMessageIdValid($messageId)) {
478                 // Then use it as message string
479                 $return = '{--' . $messageId . '--}';
480         } // END - if
481
482         // Return the status
483         return $return;
484 }
485
486 // Log the transfer
487 function logWernisTransfer ($wdsId, $amount, $type = 'FAILED', $message = '', $status = '') {
488         // Register this wernis movement
489         sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_user_wernis` (`userid`, `wernis_account`, `wernis_amount`, `wernis_timestamp`, `wernis_type`, `wernis_api_message`, `wernis_api_status`) VALUES (%s, %s, %s, UNIX_TIMESTAMP(), '%s', '%s', '%s')",
490                 array(
491                         getMemberId(),
492                         bigintval($wdsId),
493                         bigintval($amount),
494                         $type,
495                         $message,
496                         $status
497                 ), __FUNCTION__, __LINE__);
498 }
499
500 // Calulcate fees and factor
501 function calculateWernisFee ($points, $mode) {
502         // Payout or withdraw are allowed modes!
503         //* DEBUG: */ debugOutput('mode=' . $mode . ',points=' . $points);
504         if (!in_array($mode, array('payout', 'withdraw'))) {
505                 // Log error and abort
506                 logDebugMessage(__FUNCTION__, __LINE__, 'userid=' . getMemberId() . ',mode=' . $mode . ',points=' . $points . ' - unknown mode detected.');
507                 return FALSE;
508         } // END - if
509
510         // Is there a percentage or fixed fee?
511         if (getConfig('wernis_' . $mode . '_fee_percent') > 0) {
512                 // Percentage fee
513                 $points -= $points * getConfig('wernis_'.$mode.'_fee_percent') / 100;
514         } elseif (getConfig('wernis_' . $mode . '_fee_fix') > 0) {
515                 // Fixed fee
516                 $points -= getConfig('wernis_' . $mode . '_fee_fix');
517         }
518
519         // Divide/multiply the factor
520         if ($mode == 'payout') {
521                 // Divide for payout
522                 $points = $points / getWernisPayoutFactor();
523         } else {
524                 // Multiply for withdraw
525                 $points = $points * getWernisWithdrawFactor();
526         }
527
528         // Return value
529         //* DEBUG: */ debugOutput('mode=' . $mode . ',points=' . $points);
530         return $points;
531 }
532
533 // Add withdraw fees and factor
534 // @TODO Unused?
535 function calulcateWernisWithdrawFee ($points) {
536         // Is there a percentage or fixed fee?
537         if (getWernisWithdrawFeePercent() > 0) {
538                 // Percentage fee
539                 $points += $points * getWernisWithdrawFeePercent() / 100;
540         } elseif (getWernisWithdrawFeeFix() > 0) {
541                 // Fixed fee
542                 $points += getWernisWithdrawFeeFix();
543         }
544
545         // Return value
546         return $points;
547 }
548
549 // Displays registration form for WDS66 registration
550 function doDisplayWernisUserRegistrationForm () {
551         // Is the form sent?
552         if (isFormSent('register')) {
553                 // Is wernis_id set?
554                 if (!isPostRequestElementSet('wernis_id')) {
555                         // Id not set
556                         displayMessage('{--GUEST_WERNIS_REGISTRATION_ID_NOT_SET--}');
557                 } elseif (!isPostRequestElementSet('wernis_password')) {
558                         // Password not set
559                         displayMessage('{--GUEST_WERNIS_REGISTRATION_PASSWORD_NOT_SET--}');
560                 } else {
561                         // So far, all fine, then let's do the call-back on auth.php ...
562                         $args = executeWernisApiAuth(postRequestElement('wernis_id'), postRequestElement('wernis_password'));
563
564                         // Status was okay?
565                         if (isHttpResponseStatusOkay($args)) {
566                                 // Is auth_status set?
567                                 //* DEBUG-DIE */ die('response=<pre>' . print_r($response, TRUE) . '</pre>,args=' . '<pre>'.print_r($args, TRUE).'</pre>');
568                                 assert(isset($args['auth_status']));
569
570                                 // Add WDS66 userid
571                                 $args['wernis_userid'] = postRequestElement('wernis_id');
572
573                                 // "Detect" auth status
574                                 $callbackFunction = 'doWernisAuth' . capitalizeUnderscoreString($args['auth_status']);
575
576                                 // Is the call-back there?
577                                 if (!is_callable($callbackFunction, FALSE, $callableName)) {
578                                         // Not there, could be bad. :(
579                                         reportBug(__FUNCTION__, __LINE__, 'Unsupported auth_status=' . $args['auth_status'] . ',args()=' . count($args) . ',callbackFunction=' . $callbackFunction . ' detected.');
580                                 } // END - if
581
582                                 // Then call it
583                                 $status = call_user_func($callbackFunction, $args);
584
585                                 // @TODO Something more to do here?
586                                 die(__FUNCTION__ . ':' . __LINE__ . ': status[' . gettype($status) . ']=' . $status . ' - Unfinished.');
587                         } else {
588                                 // Something bad happened
589                                 displayMessage($args['message']);
590                         }
591                 }
592         } // END - if
593
594         // Is there a challenge + response?
595         if ((isGetRequestElementSet('status')) && (isGetRequestElementSet('challenge')) && (isGetRequestElementSet('__challenge_response'))) {
596                 // Redirect from modules.php?module=auth, so validate challenge response ...
597                 // 1) Get first 24 characters = salt
598                 $salt = substr(getRequestElement('__challenge_response'), 0, 24);
599
600                 // 2) Generate hash for challenge response
601                 $challengeResponse = $salt . hashSha256($salt . getWernisApiMd5() . getRequestElement('challenge'));
602
603                 // Is the response valid?
604                 if ($challengeResponse != getRequestElement('__challenge_response')) {
605                         // Not valid
606                         displayMessage('{--GUEST_WERNIS_REGISTRATION_INVALID_CHALLENGE_RESPONSE--}');
607                         return;
608                 } // END - if
609
610                 /*
611                  * Now, that the challenge-response is the same, the challenge itself
612                  * is also the same. Next get the data from wernis_regs table by
613                  * challenge. There is currently no other way to get the data as there
614                  * is no Wernis user id provided. Later on the stored challenge response
615                  * can be compared with provided.
616                  */
617                 $return = doWernisFinishUserRegistration(getRequestElement('challenge'), getRequestElement('__challenge_response'), getRequestElement('status'));
618
619                 // Is the registration finished?
620                 if ($return === FALSE) {
621                         // No, then abort here silently as the function should have already displayed a message
622                         return;
623                 } // END - if
624         } elseif (!isFormSent('register')) {
625                 // Form not send, so load form template
626                 loadTemplate('guest_wernis_registration_rpc_form');
627         }
628 }
629
630 // Finish user registration with WDS66 API
631 function doWernisFinishUserRegistration ($challenge, $challengeResponse, $status) {
632         // Is the status 1? (= all fine with API call)
633         if ($status == '1') {
634                 // Get mapped data based on challenge
635                 $return = getWernisMappedDataFromApiByChallenge($challenge, $challengeResponse, $status);
636
637                 // Is the array filled?
638                 //* DEBUG-DIE */ die(__METHOD__ . ':return=<pre>' . print_r($return, TRUE) . '</pre> - EXIT!');
639                 if ((isset($return['mapped_data'])) && (count($return['mapped_data']) > 0) && (empty($return['message']))) {
640                         // Set must-fillout fields
641                         $return['mapped_data'] = runFilterChain('register_must_fillout', $return['mapped_data']);
642
643                         // Add missing elements
644                         $return['mapped_data']['gender']               = NULL;
645                         $return['mapped_data']['birthday_selection']   = generateDayMonthYearSelectionBox($return['mapped_data']['birth_day'], $return['mapped_data']['birth_month'], $return['mapped_data']['birth_year']);
646                         $return['mapped_data']['challenge']            = getRequestElement('challenge');
647                         $return['mapped_data']['__challenge_response'] = getRequestElement('__challenge_response');
648
649                         // Display form
650                         loadTemplate('guest_wernis_registration_form', FALSE, $return['mapped_data']);
651
652                         // All fine
653                         return TRUE;
654                 } else {
655                         // Something unexpected happened (e.g. no API requests left)
656                         displayMessage($return['message']);
657                         return FALSE;
658                 }
659         } else {
660                 // Not accepted
661                 displayMessage('{--GUEST_WERNIS_REGISTRATION_AUTH_REJECTED--}');
662         }
663 }
664
665 // "Getter" for mapped data by calling the API and given challenge and status
666 function getWernisMappedDataFromApiByChallenge ($challenge, $challengeResponse, $status) {
667         // Get stored registration data
668         $rows = getWernisRegistrationDataByKey('api_redirect_challenge', $challenge);
669
670         // Zero result found?
671         if (count($rows) == 0) {
672                 // Nothing found
673                 displayMessage('{--GUEST_WERNIS_REGISTRATION_ZERO_ROWS_FOUND--}');
674
675                 // Display form
676                 loadTemplate('guest_wernis_registration_rpc_form');
677                 return array();
678         } // END - if
679
680         // Init array
681         $return = array(
682                 // Mapped data
683                 'mapped_data' => array(),
684                 // Any error message from API
685                 'message'     => ''
686         );
687
688         // Has the auth status changed?
689         if ($rows[0]['api_auth_status'] != 'ACCEPTED') {
690                 /*
691                  * The authorization of this application has been accepted, so
692                  * update it and ignore result from function because the update
693                  * will always run.
694                  */
695                 updateWernisRegistrationDataByKey('api_auth_status', 'api_redirect_challenge', $challenge, 'ACCEPTED');
696                 updateWernisRegistrationDataByKey('api_challenge_response', 'api_redirect_challenge', $challenge, $challengeResponse);
697         } // END - if
698
699         // Now call "get.php"
700         $response = executeWernisApiGet($rows[0], 'data', 'vorname|name|strasse|plz|ort|birth_day|birth_month|birth_year|email|werber');
701
702         // Was the status okay?
703         //* DEBUG-DIE */ die(__FUNCTION__ . ':response=<pre>' . print_r($response, TRUE) . '</pre>');
704         if (isHttpResponseStatusOkay($response)) {
705                 // API returned non-errous response, 'data=' must be found
706                 assert(isset($response['data']));
707
708                 // And decode it (all steps separated to later "easily" debug them)
709                 $decodedData = base64_decode(urldecode($response['data']));
710                 //* DEBUG-DIE */ die(__FUNCTION__ . ':decodedData=' . $decodedData);
711
712                 /*
713                  * Do some checks on the decoded string, it should be a
714                  * serialized array with 10 entries (see above
715                  * executeWernisApiGet() call).
716                  */
717                 assert(substr($decodedData, 0, 6) == 'a:10:{');
718                 assert(substr($decodedData, -1, 1) == '}');
719
720                 // The array seems to be fine, unserialize it
721                 $userData = unserialize($decodedData);
722                 //* DEBUG-DIE */ die(__METHOD__ . ':userData=<pre>' . print_r($userData, TRUE) . '</pre> - EXIT!');
723
724                 // All mappings WDS66->mailer
725                 $mappings = array(
726                         'vorname'     => 'surname',
727                         'name'        => 'family',
728                         'strasse'     => 'street_nr',
729                         'plz'         => 'zip',
730                         'ort'         => 'city',
731                         'email'       => 'email',
732                         'birth_day'   => 'birth_day',
733                         'birth_month' => 'birth_month',
734                         'birth_year'  => 'birth_year',
735                         'werber'      => 'wernis_refid'
736                 );
737
738                 // Map all WDS66 entries into mailer entries
739                 foreach ($mappings as $from => $to) {
740                         // All must exist
741                         if (!isset($userData[$from])) {
742                                 // Element $from does not exist
743                                 reportBug(__FUNCTION__, __LINE__, 'Cannot map from=' . $from . ' -> to=' . $to . ': element does not exist.');
744                         } // END - if
745
746                         // "Map" all and make empty strings to NULL
747                         $return['mapped_data'][$to] = convertEmptyToNull($userData[$from]);
748                 } // END - foreach
749
750                 // Both arrays must have same size
751                 assert(count($userData) == count($return['mapped_data']));
752
753                 // Now add userid from WDS66
754                 $return['mapped_data']['wernis_userid'] = bigintval($rows[0]['wernis_userid']);
755         } else {
756                 // Something bad happened so copy the message
757                 $return['message'] = $response['message'];
758         }
759
760         // Return mapped data array
761         //* DEBUG-DIE */ die(__METHOD__ . ':return=<pre>' . print_r($return, TRUE) . '</pre> - EXIT!');
762         return $return;
763 }
764
765 // Updates auth status by given key/value pair
766 function updateWernisRegistrationDataByKey ($updatedColumn, $key, $oldValue, $newValue) {
767         // Run the update
768         sqlQueryEscaped("UPDATE
769         `{?_MYSQL_PREFIX?}_wernis_regs`
770 SET
771         `%s` = '%s'
772 WHERE
773         `%s` = '%s' AND
774         `%s` != '%s'
775 LIMIT 1",
776                 array(
777                         $updatedColumn,
778                         $newValue,
779                         $key,
780                         $oldValue,
781                         $updatedColumn,
782                         $oldValue
783                 ), __FUNCTION__, __LINE__
784         );
785
786         // Check if rows as been affected
787         return ifSqlHasZeroAffectedRows();
788 }
789
790 // "Getter" for Wernis registration data by given key and value
791 function getWernisRegistrationDataByKey ($key, $value, $limit = 1) {
792         // Init array
793         $rows = array();
794
795         // Now search for it
796         $result = sqlQueryEscaped("SELECT
797         `local_userid`,
798         `wernis_userid`,
799         `api_auth_status`,
800         `api_auth_key`,
801         `api_redirect_challenge`,
802         `api_challenge_response`,
803         UNIX_TIMESTAMP(`record_inserted`) AS `record_inserted`
804 FROM
805         `{?_MYSQL_PREFIX?}_wernis_regs`
806 WHERE
807         `%s`='%s'
808 ORDER BY
809         `id`
810 LIMIT %d",
811                 array(
812                         $key,
813                         $value,
814                         $limit
815                 ), __FUNCTION__, __LINE__
816         );
817
818         // Is there an entry?
819         if (sqlNumRows($result) > 0) {
820                 // At least one entry has been found, so loop through all
821                 while ($row = sqlFetchArray($result)) {
822                         // Add it
823                         array_push($rows, $row);
824                 } // END - while
825         } // END - if
826
827         // Free result
828         sqlFreeResult($result);
829
830         // Return found entries
831         return $rows;
832 }
833
834 // Do local user registration with data from WDS66 API
835 function doWernisUserRegistration () {
836         // Call generic registration function
837         $status = doGenericUserRegistration();
838
839         // Does this went fine?
840         if ($status === FALSE) {
841                 // No, then abort here silently
842                 return FALSE;
843         } // END - if
844
845         // Make sure the user id is valid
846         assert(isset($GLOBALS['register_userid']));
847         assert(isValidId($GLOBALS['register_userid']));
848
849         // Generic registration is finished, so add more data:
850 }
851
852 // Generates decrption key based on private key, public key and API key
853 function generateWernisDecryptionKey ($publicKey) {
854         // Generate key from most known data
855         $key = hashSha256(sprintf(
856                 '%s:%s:%s',
857                 getWernisApiMd5(),
858                 getWernisPrivateKey(),
859                 $publicKey
860         ));
861
862         // Return it
863         return $key;
864 }
865
866 //-----------------------------------------------------------------------------
867 //                      Auth status callback functions
868 //-----------------------------------------------------------------------------
869
870 // Handler for auth_status=PENDING
871 function doWernisAuthPending ($args) {
872         // $args must always be an array
873         assert(is_array($args));
874
875         // auth_key and wernis_userid must be set
876         assert(isset($args['auth_key']));
877         assert(isset($args['wernis_userid']));
878
879         // Generate a challenge that will be added to the URL
880         $challenge = hashSha256(generatePassword(128));
881
882         // Search entry in database by auth_key
883         if (countSumTotalData($args['auth_key'], 'wernis_regs', 'id', 'api_auth_key', TRUE) == 0) {
884                 // "Register" this call
885                 sqlQueryEscaped("INSERT INTO `{?_MYSQL_PREFIX?}_wernis_regs` (
886         `wernis_userid`,
887         `api_auth_status`,
888         `api_auth_key`,
889         `api_redirect_challenge`
890 ) VALUES (
891         %s,
892         'PENDING',
893         '%s',
894         '%s'
895 )",
896                         array(
897                                 bigintval($args['wernis_userid']),
898                                 $args['auth_key'],
899                                 $challenge
900                         ), __FUNCTION__, __LINE__
901                 );
902         } else {
903                 // Update challenge
904                 sqlQueryEscaped("UPDATE
905         `{?_MYSQL_PREFIX?}_wernis_regs`
906 SET
907         `api_redirect_challenge`='%s'
908 WHERE
909         `api_auth_key`='%s' AND
910         `wernis_userid`=%s AND
911         `api_auth_status`='PENDING'
912 LIMIT 1",
913                         array(
914                                 $challenge,
915                                 $args['auth_key'],
916                                 bigintval($args['wernis_userid'])
917                         ), __FUNCTION__, __LINE__
918                 );
919         }
920
921         // Should always update/insert
922         assert(sqlAffectedRows() == 1);
923
924         // Redirect to WDS66 module=auth ...
925         //* DEBUG-DIE */ die(__FUNCTION__ . ':' . __LINE__ . '<pre>' . print_r($args, TRUE) . '</pre>');
926         redirectToUrl(getWernisBaseUrl() . '/modules.php?module=auth&amp;auth_key=' . trim($args['auth_key']) . '&amp;params=' . urlencode(base64_encode('&module=' . getModule() . '&what=' . getWhat())) . '&amp;challenge=' . $challenge, FALSE, FALSE);
927 }
928
929 // Handler for auth_status=ACCEPTED
930 function doWernisAuthAccepted ($args) {
931         // $args must always be an array
932         assert(is_array($args));
933
934         // auth_key and wernis_userid must be set
935         assert(isset($args['auth_key']));
936         assert(isset($args['wernis_userid']));
937
938         // Get registration data by auth_key
939         $rows = getWernisRegistrationDataByKey('api_auth_key', $args['auth_key']);
940
941         // The userid should be same
942         assert(isset($rows[0]['wernis_userid']));
943         assert($rows[0]['wernis_userid'] === $args['wernis_userid']);
944
945         // Check both challenge + response
946         assert(isset($rows[0]['api_redirect_challenge']));
947         assert(isset($rows[0]['api_challenge_response']));
948
949         // Both are fine, so get the data
950         $return = doWernisFinishUserRegistration($rows[0]['api_redirect_challenge'], $rows[0]['api_challenge_response'], '1');
951
952         // All fine?
953         if ($return === FALSE) {
954                 // @TODO Should not happen???
955                 reportBug(__FUNCTION__, __LINE__, 'args=<pre>' . print_r($args, TRUE) . '</pre>rows=<pre>' . print_r($rows, TRUE) . '</pre> - Failed!');
956         } // END - if
957
958         // Generate URL
959         $url = basename(detectRequestUri()) . '&amp;challenge=' . $rows[0]['api_redirect_challenge'] . '&amp;__challenge_response=' . $rows[0]['api_challenge_response'] . '&amp;status=1';
960
961         // Redirect to URL
962         redirectToUrl($url);
963 }
964
965 //------------------------------------------------------------------------------
966 //                             Template helper functions
967 //------------------------------------------------------------------------------
968
969 // Template helper to generate a selection box for encryption alogrithms
970 function doTemplateSelectWernisEncryptionAlgorithm ($templateName, $clear = FALSE, $default = NULL) {
971         // Get all available algorithms
972         $algorithms = getSupportedEncryptionAlgorithms();
973         //* DEBUG-DIE */ die('algorithms=<pre>' . print_r($algorithms, TRUE) . '</pre>');
974
975         // Init array
976         $options = array();
977
978         // And fill it
979         foreach ($algorithms as $key => $dummy) {
980                 $options[$key] = array('algorithms' => $key);
981         } // END - if
982
983         // Handle it over to generateSelectionBoxFromArray()
984         $content = generateSelectionBoxFromArray($options, 'wernis_encryption_algorithm', 'algorithms', '', '_wernis', '', $default, '', TRUE, FALSE);
985
986         // Return prepared content
987         return $content;
988 }
989
990 // Template helper to generate a selection box for encryption alogrithms
991 function doTemplateSelectWernisEncryptionMode ($templateName, $clear = FALSE, $default = NULL) {
992         // Get all available modes
993         $modes = getSupportedEncryptionModes();
994
995         // Init array
996         $options = array();
997
998         // And fill it
999         foreach ($modes as $key => $dummy) {
1000                 $options[$key] = array('modes' => $key);
1001         } // END - if
1002
1003         // Handle it over to generateSelectionBoxFromArray()
1004         $content = generateSelectionBoxFromArray($options, 'wernis_encryption_mode', 'modes', '', '_wernis', '', $default, '', TRUE, FALSE);
1005
1006         // Return prepared content
1007         return $content;
1008 }
1009
1010 //-----------------------------------------------------------------------------
1011 //                             Wrapper functions
1012 //-----------------------------------------------------------------------------
1013
1014 // Wrapper function for 'wernis_refid'
1015 function getWernisRefid () {
1016         // Is there cache?
1017         if (!isset($GLOBALS[__FUNCTION__])) {
1018                 // Get config entry
1019                 $GLOBALS[__FUNCTION__] = getConfig('wernis_refid');
1020         } // END - if
1021
1022         // Return cache
1023         return $GLOBALS[__FUNCTION__];
1024 }
1025
1026 // Wrapper function for 'wernis_pass_md5'
1027 function getWernisPassMd5 () {
1028         // Is there cache?
1029         if (!isset($GLOBALS[__FUNCTION__])) {
1030                 // Get config entry
1031                 $GLOBALS[__FUNCTION__] = getConfig('wernis_pass_md5');
1032         } // END - if
1033
1034         // Return cache
1035         return $GLOBALS[__FUNCTION__];
1036 }
1037
1038 // Wrapper function for 'wernis_api_id'
1039 function getWernisApiId () {
1040         // Is there cache?
1041         if (!isset($GLOBALS[__FUNCTION__])) {
1042                 // Get config entry
1043                 $GLOBALS[__FUNCTION__] = getConfig('wernis_api_id');
1044         } // END - if
1045
1046         // Return cache
1047         return $GLOBALS[__FUNCTION__];
1048 }
1049
1050 // Wrapper function for 'wernis_api_md5'
1051 function getWernisApiMd5 () {
1052         // Is there cache?
1053         if (!isset($GLOBALS[__FUNCTION__])) {
1054                 // Get config entry
1055                 $GLOBALS[__FUNCTION__] = getConfig('wernis_api_md5');
1056         } // END - if
1057
1058         // Return cache
1059         return $GLOBALS[__FUNCTION__];
1060 }
1061
1062 // Wrapper function for 'wernis_api_url'
1063 function getWernisApiUrl () {
1064         // Is there cache?
1065         if (!isset($GLOBALS[__FUNCTION__])) {
1066                 // Get config entry
1067                 $GLOBALS[__FUNCTION__] = getConfig('wernis_api_url');
1068         } // END - if
1069
1070         // Return cache
1071         return $GLOBALS[__FUNCTION__];
1072 }
1073
1074 // Wrapper function for 'wernis_withdraw_active'
1075 function getWernisWithdrawActive () {
1076         // Is there cache?
1077         if (!isset($GLOBALS[__FUNCTION__])) {
1078                 // Get config entry
1079                 $GLOBALS[__FUNCTION__] = getConfig('wernis_withdraw_active');
1080         } // END - if
1081
1082         // Return cache
1083         return $GLOBALS[__FUNCTION__];
1084 }
1085
1086 // Wrapper function for 'wernis_payout_active'
1087 function getWernisPayoutActive () {
1088         // Is there cache?
1089         if (!isset($GLOBALS[__FUNCTION__])) {
1090                 // Get config entry
1091                 $GLOBALS[__FUNCTION__] = getConfig('wernis_payout_active');
1092         } // END - if
1093
1094         // Return cache
1095         return $GLOBALS[__FUNCTION__];
1096 }
1097
1098 // Wrapper function for 'wernis_withdraw_active'
1099 function isWernisWithdrawActive () {
1100         // Is there cache?
1101         if (!isset($GLOBALS[__FUNCTION__])) {
1102                 // Get config entry
1103                 $GLOBALS[__FUNCTION__] = (getConfig('wernis_withdraw_active') == 'Y');
1104         } // END - if
1105
1106         // Return cache
1107         return $GLOBALS[__FUNCTION__];
1108 }
1109
1110 // Wrapper function for 'wernis_payout_active'
1111 function isWernisPayoutActive () {
1112         // Is there cache?
1113         if (!isset($GLOBALS[__FUNCTION__])) {
1114                 // Get config entry
1115                 $GLOBALS[__FUNCTION__] = (getConfig('wernis_payout_active') == 'Y');
1116         } // END - if
1117
1118         // Return cache
1119         return $GLOBALS[__FUNCTION__];
1120 }
1121
1122 // Wrapper function for 'wernis_withdraw_factor'
1123 function getWernisWithdrawFactor () {
1124         // Is there cache?
1125         if (!isset($GLOBALS[__FUNCTION__])) {
1126                 // Get config entry
1127                 $GLOBALS[__FUNCTION__] = getConfig('wernis_withdraw_factor');
1128         } // END - if
1129
1130         // Return cache
1131         return $GLOBALS[__FUNCTION__];
1132 }
1133
1134 // Wrapper function for 'wernis_payout_factor'
1135 function getWernisPayoutFactor () {
1136         // Is there cache?
1137         if (!isset($GLOBALS[__FUNCTION__])) {
1138                 // Get config entry
1139                 $GLOBALS[__FUNCTION__] = getConfig('wernis_payout_factor');
1140         } // END - if
1141
1142         // Return cache
1143         return $GLOBALS[__FUNCTION__];
1144 }
1145
1146 // Wrapper function for 'wernis_withdraw_fee_percent'
1147 function getWernisWithdrawFeePercent () {
1148         // Is there cache?
1149         if (!isset($GLOBALS[__FUNCTION__])) {
1150                 // Get config entry
1151                 $GLOBALS[__FUNCTION__] = getConfig('wernis_withdraw_fee_percent');
1152         } // END - if
1153
1154         // Return cache
1155         return $GLOBALS[__FUNCTION__];
1156 }
1157
1158 // Wrapper function for 'wernis_withdraw_fee_fix'
1159 function getWernisWithdrawFeeFix () {
1160         // Is there cache?
1161         if (!isset($GLOBALS[__FUNCTION__])) {
1162                 // Get config entry
1163                 $GLOBALS[__FUNCTION__] = getConfig('wernis_withdraw_fee_fix');
1164         } // END - if
1165
1166         // Return cache
1167         return $GLOBALS[__FUNCTION__];
1168 }
1169
1170 // Wrapper function for 'wernis_payout_fee_percent'
1171 function getWernisPayoutFeePercent () {
1172         // Is there cache?
1173         if (!isset($GLOBALS[__FUNCTION__])) {
1174                 // Get config entry
1175                 $GLOBALS[__FUNCTION__] = getConfig('wernis_payout_fee_percent');
1176         } // END - if
1177
1178         // Return cache
1179         return $GLOBALS[__FUNCTION__];
1180 }
1181
1182 // Wrapper function for 'wernis_payout_fee_fix'
1183 function getWernisPayoutFeeFix () {
1184         // Is there cache?
1185         if (!isset($GLOBALS[__FUNCTION__])) {
1186                 // Get config entry
1187                 $GLOBALS[__FUNCTION__] = getConfig('wernis_payout_fee_fix');
1188         } // END - if
1189
1190         // Return cache
1191         return $GLOBALS[__FUNCTION__];
1192 }
1193
1194 // Wrapper function for 'wernis_min_payout'
1195 function getWernisMinPayout () {
1196         // Is there cache?
1197         if (!isset($GLOBALS[__FUNCTION__])) {
1198                 // Get config entry
1199                 $GLOBALS[__FUNCTION__] = getConfig('wernis_min_payout');
1200         } // END - if
1201
1202         // Return cache
1203         return $GLOBALS[__FUNCTION__];
1204 }
1205
1206 // Wrapper function for 'wernis_min_withdraw'
1207 function getWernisMinWithdraw () {
1208         // Is there cache?
1209         if (!isset($GLOBALS[__FUNCTION__])) {
1210                 // Get config entry
1211                 $GLOBALS[__FUNCTION__] = getConfig('wernis_min_withdraw');
1212         } // END - if
1213
1214         // Return cache
1215         return $GLOBALS[__FUNCTION__];
1216 }
1217
1218 // Wrapper function for 'wernis_base_url'
1219 function getWernisBaseUrl () {
1220         // Is there cache?
1221         if (!isset($GLOBALS[__FUNCTION__])) {
1222                 // Get config entry
1223                 $GLOBALS[__FUNCTION__] = getConfig('wernis_base_url');
1224         } // END - if
1225
1226         // Return cache
1227         return $GLOBALS[__FUNCTION__];
1228 }
1229
1230 // Wrapper function for 'wernis_encryption_algorithm'
1231 function getWernisEncryptionAlgorithm () {
1232         // Is there cache?
1233         if (!isset($GLOBALS[__FUNCTION__])) {
1234                 // Get config entry
1235                 $GLOBALS[__FUNCTION__] = getConfig('wernis_encryption_algorithm');
1236         } // END - if
1237
1238         // Return cache
1239         return $GLOBALS[__FUNCTION__];
1240 }
1241
1242 // Wrapper function for 'wernis_encryption_mode'
1243 function getWernisEncryptionMode () {
1244         // Is there cache?
1245         if (!isset($GLOBALS[__FUNCTION__])) {
1246                 // Get config entry
1247                 $GLOBALS[__FUNCTION__] = getConfig('wernis_encryption_mode');
1248         } // END - if
1249
1250         // Return cache
1251         return $GLOBALS[__FUNCTION__];
1252 }
1253
1254 // Wrapper function for 'wernis_private_key'
1255 function getWernisPrivateKey () {
1256         // Is there cache?
1257         if (!isset($GLOBALS[__FUNCTION__])) {
1258                 // Get config entry
1259                 $GLOBALS[__FUNCTION__] = getConfig('wernis_private_key');
1260         } // END - if
1261
1262         // Return cache
1263         return $GLOBALS[__FUNCTION__];
1264 }
1265
1266 // [EOF]
1267 ?>