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