1: <?php
2:
3:
4:
5: if (!class_exists('XoopsGTicket')) {
6:
7: 8: 9:
10: class XoopsGTicket
11: {
12: public $_errors = array();
13: public $_latest_token = '';
14: public $messages = array();
15:
16: 17: 18:
19: public function __construct()
20: {
21: global $xoopsConfig;
22:
23:
24: if (defined('XOOPS_ROOT_PATH') && !empty($xoopsConfig['language']) && false === strpos($xoopsConfig['language'], '/')) {
25: if (file_exists(dirname(__DIR__) . '/language/' . $xoopsConfig['language'] . '/gticket_messages.phtml')) {
26: include dirname(__DIR__) . '/language/' . $xoopsConfig['language'] . '/gticket_messages.phtml';
27: }
28: }
29:
30:
31: if (empty($this->messages)) {
32: $this->messages = array(
33: 'err_general' => 'GTicket Error',
34: 'err_nostubs' => 'No stubs found',
35: 'err_noticket' => 'No ticket found',
36: 'err_nopair' => 'No valid ticket-stub pair found',
37: 'err_timeout' => 'Time out',
38: 'err_areaorref' => 'Invalid area or referer',
39: 'fmt_prompt4repost' => 'error(s) found:<br><span style="background-color:red;font-weight:bold;color:white;">%s</span><br>Confirm it.<br>And do you want to post again?',
40: 'btn_repost' => 'repost');
41: }
42: }
43:
44:
45: 46: 47: 48: 49: 50: 51:
52: public function getTicketHtml($salt = '', $timeout = 1800, $area = '')
53: {
54: return '<input type="hidden" name="XOOPS_G_TICKET" value="' . $this->issue($salt, $timeout, $area) . '" />';
55: }
56:
57:
58: 59: 60: 61: 62: 63: 64:
65: public function getTicketXoopsForm($salt = '', $timeout = 1800, $area = '')
66: {
67: return new XoopsFormHidden('XOOPS_G_TICKET', $this->issue($salt, $timeout, $area));
68: }
69:
70:
71: 72: 73: 74: 75: 76:
77: public function addTicketXoopsFormElement(&$form, $salt = '', $timeout = 1800, $area = '')
78: {
79: $form->addElement(new XoopsFormHidden('XOOPS_G_TICKET', $this->issue($salt, $timeout, $area)));
80: }
81:
82:
83: 84: 85: 86: 87: 88: 89:
90: public function getTicketArray($salt = '', $timeout = 1800, $area = '')
91: {
92: return array('XOOPS_G_TICKET' => $this->issue($salt, $timeout, $area));
93: }
94:
95:
96: 97: 98: 99: 100: 101: 102: 103:
104: public function getTicketParamString($salt = '', $noamp = false, $timeout = 1800, $area = '')
105: {
106: return ($noamp ? '' : '&') . 'XOOPS_G_TICKET=' . $this->issue($salt, $timeout, $area);
107: }
108:
109:
110: 111: 112: 113: 114: 115: 116:
117: public function issue($salt = '', $timeout = 1800, $area = '')
118: {
119: global $xoopsModule;
120:
121: if ('' === $salt) {
122: $salt = '$2y$07$' . str_replace('+', '.', base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)));
123: }
124:
125:
126: list($usec, $sec) = explode(' ', microtime());
127: $appendix_salt = empty($_SERVER['PATH']) ? XOOPS_DB_NAME : $_SERVER['PATH'];
128: $token = crypt($salt . $usec . $appendix_salt . $sec, $salt);
129: $this->_latest_token = $token;
130:
131: if (empty($_SESSION['XOOPS_G_STUBS'])) {
132: $_SESSION['XOOPS_G_STUBS'] = array();
133: }
134:
135:
136: if (count($_SESSION['XOOPS_G_STUBS']) > 10) {
137: $_SESSION['XOOPS_G_STUBS'] = array_slice($_SESSION['XOOPS_G_STUBS'], -10);
138: }
139:
140:
141: $referer = empty($_SERVER['HTTP_REFERER']) ? '' : $_SERVER['REQUEST_URI'];
142:
143:
144: if (!$area && is_object(@$xoopsModule)) {
145: $area = $xoopsModule->getVar('dirname');
146: }
147:
148:
149: $_SESSION['XOOPS_G_STUBS'][] = array(
150: 'expire' => time() + $timeout,
151: 'referer' => $referer,
152: 'area' => $area,
153: 'token' => $token);
154:
155:
156: return md5($token . XOOPS_DB_PREFIX);
157: }
158:
159:
160: 161: 162: 163: 164: 165: 166:
167: public function check($post = true, $area = '', $allow_repost = true)
168: {
169: global $xoopsModule;
170:
171: $this->_errors = array();
172:
173:
174: if (!is_array(@$_SESSION['XOOPS_G_STUBS'])) {
175: $this->_errors[] = $this->messages['err_nostubs'];
176: $_SESSION['XOOPS_G_STUBS'] = array();
177: }
178:
179:
180: $ticket = $post ? @$_POST['XOOPS_G_TICKET'] : @$_GET['XOOPS_G_TICKET'];
181:
182:
183: if (empty($ticket)) {
184: $this->_errors[] = $this->messages['err_noticket'];
185: }
186:
187:
188: $stubs_tmp = $_SESSION['XOOPS_G_STUBS'];
189: $_SESSION['XOOPS_G_STUBS'] = array();
190: foreach ($stubs_tmp as $stub) {
191:
192: if ($stub['expire'] >= time()) {
193: if (md5($stub['token'] . XOOPS_DB_PREFIX) === $ticket) {
194: $found_stub = $stub;
195: } else {
196:
197: $_SESSION['XOOPS_G_STUBS'][] = $stub;
198: }
199: } else {
200: if (md5($stub['token'] . XOOPS_DB_PREFIX) === $ticket) {
201:
202: $timeout_flag = true;
203: }
204: }
205: }
206:
207:
208: if (empty($found_stub)) {
209: if (empty($timeout_flag)) {
210: $this->_errors[] = $this->messages['err_nopair'];
211: } else {
212: $this->_errors[] = $this->messages['err_timeout'];
213: }
214: } else {
215:
216:
217:
218: if (!$area && is_object(@$xoopsModule)) {
219: $area = $xoopsModule->getVar('dirname');
220: }
221:
222:
223: if (@$found_stub['area'] == $area) {
224: $area_check = true;
225: }
226: if (!empty($found_stub['referer']) && false !== strpos(@$_SERVER['HTTP_REFERER'], $found_stub['referer'])) {
227: $referer_check = true;
228: }
229:
230: if (empty($area_check) && empty($referer_check)) {
231: $this->_errors[] = $this->messages['err_areaorref'];
232: }
233: }
234:
235: if (!empty($this->_errors)) {
236: if ($allow_repost) {
237:
238: $this->draw_repost_form($area);
239: exit;
240: } else {
241:
242: $this->clear();
243:
244: return false;
245: }
246: } else {
247:
248: return true;
249: }
250: }
251:
252:
253: 254: 255:
256: public function draw_repost_form($area = '')
257: {
258:
259: if (headers_sent()) {
260: restore_error_handler();
261: set_error_handler(array(&$this, 'errorHandler4FindOutput'));
262: header('Dummy: for warning');
263: restore_error_handler();
264: exit;
265: }
266:
267: error_reporting(0);
268: while (ob_get_level()) {
269: ob_end_clean();
270: }
271:
272: $table = '<table>';
273: $form = '<form action="?' . htmlspecialchars(@$_SERVER['QUERY_STRING'], ENT_QUOTES) . '" method="post" >';
274: foreach ($_POST as $key => $val) {
275: if ($key === 'XOOPS_G_TICKET') {
276: continue;
277: }
278: if (get_magic_quotes_gpc()) {
279: $key = stripslashes($key);
280: }
281: if (is_array($val)) {
282: list($tmp_table, $tmp_form) = $this->extract_post_recursive(htmlspecialchars($key, ENT_QUOTES), $val);
283: $table .= $tmp_table;
284: $form .= $tmp_form;
285: } else {
286: if (get_magic_quotes_gpc()) {
287: $val = stripslashes($val);
288: }
289: $table .= '<tr><th>' . htmlspecialchars($key, ENT_QUOTES) . '</th><td>' . htmlspecialchars($val, ENT_QUOTES) . '</td></tr>' . "\n";
290: $form .= '<input type="hidden" name="' . htmlspecialchars($key, ENT_QUOTES) . '" value="' . htmlspecialchars($val, ENT_QUOTES) . '" />' . "\n";
291: }
292: }
293: $table .= '</table>';
294: $form .= $this->getTicketHtml(__LINE__, 300, $area) . '<input type="submit" value="' . $this->messages['btn_repost'] . '" /></form>';
295:
296: echo '<html><head><title>' . $this->messages['err_general'] . '</title><style>table,td,th {border:solid black 1px; border-collapse:collapse;}</style></head><body>' . sprintf($this->messages['fmt_prompt4repost'], $this->getErrors()) . $table . $form . '</body></html>';
297: }
298:
299: 300: 301: 302: 303: 304:
305: public function extract_post_recursive($key_name, $tmp_array)
306: {
307: $table = '';
308: $form = '';
309: foreach ($tmp_array as $key => $val) {
310: if (get_magic_quotes_gpc()) {
311: $key = stripslashes($key);
312: }
313: if (is_array($val)) {
314: list($tmp_table, $tmp_form) = $this->extract_post_recursive($key_name . '[' . htmlspecialchars($key, ENT_QUOTES) . ']', $val);
315: $table .= $tmp_table;
316: $form .= $tmp_form;
317: } else {
318: if (get_magic_quotes_gpc()) {
319: $val = stripslashes($val);
320: }
321: $table .= '<tr><th>' . $key_name . '[' . htmlspecialchars($key, ENT_QUOTES) . ']</th><td>' . htmlspecialchars($val, ENT_QUOTES) . '</td></tr>' . "\n";
322: $form .= '<input type="hidden" name="' . $key_name . '[' . htmlspecialchars($key, ENT_QUOTES) . ']" value="' . htmlspecialchars($val, ENT_QUOTES) . '" />' . "\n";
323: }
324: }
325:
326: return array($table, $form);
327: }
328:
329:
330: public function clear()
331: {
332: $_SESSION['XOOPS_G_STUBS'] = array();
333: }
334:
335:
336: 337: 338:
339: public function using()
340: {
341: if (!empty($_SESSION['XOOPS_G_STUBS'])) {
342: return true;
343: } else {
344: return false;
345: }
346: }
347:
348:
349: 350: 351: 352: 353:
354: public function getErrors($ashtml = true)
355: {
356: if ($ashtml) {
357: $ret = '';
358: foreach ($this->_errors as $msg) {
359: $ret .= "$msg<br>\n";
360: }
361: } else {
362: $ret = $this->_errors;
363: }
364:
365: return $ret;
366: }
367:
368: 369: 370: 371: 372: 373: 374:
375: public function errorHandler4FindOutput($errNo, $errStr, $errFile, $errLine)
376: {
377: if (preg_match('?' . preg_quote(XOOPS_ROOT_PATH) . '([^:]+)\:(\d+)?', $errStr, $regs)) {
378: echo 'Irregular output! check the file ' . htmlspecialchars($regs[1]) . ' line ' . htmlspecialchars($regs[2]);
379: } else {
380: echo 'Irregular output! check language files etc.';
381: }
382:
383: return null;
384: }
385:
386: }
387:
388:
389: $GLOBALS['xoopsGTicket'] = new XoopsGTicket();
390: }
391:
392: if (!function_exists('admin_refcheck')) {
393:
394:
395: 396: 397: 398: 399:
400: function admin_refcheck($chkref = '')
401: {
402: if (empty($_SERVER['HTTP_REFERER'])) {
403: return true;
404: } else {
405: $ref = $_SERVER['HTTP_REFERER'];
406: }
407: $cr = XOOPS_URL;
408: if ($chkref != '') {
409: $cr .= $chkref;
410: }
411: return !(strpos($ref, $cr) !== 0);
412: }
413: }
414: