XOOPS 2.5.6  Final
 All Classes Namespaces Files Functions Variables Pages
gtickets.php
Go to the documentation of this file.
1 <?php
2 // GIJOE's Ticket Class (based on Marijuana's Oreteki XOOPS)
3 // nobunobu's suggestions are applied
4 
5 if( ! class_exists( 'XoopsGTicket' ) ) {
6 
7 class XoopsGTicket {
8 
9  var $_errors = array() ;
10  var $_latest_token = '' ;
11  var $messages = array() ;
12 
13  function XoopsGTicket()
14  {
15  global $xoopsConfig ;
16 
17  // language file
18  if( defined( 'XOOPS_ROOT_PATH' ) && ! empty( $xoopsConfig['language'] ) && ! strstr( $xoopsConfig['language'] , '/' ) ) {
19  if( file_exists( dirname( dirname( __FILE__ ) ) . '/language/' . $xoopsConfig['language'] . '/gticket_messages.phtml' ) ) {
20  include dirname( dirname( __FILE__ ) ) . '/language/' . $xoopsConfig['language'] . '/gticket_messages.phtml' ;
21  }
22  }
23 
24  // default messages
25  if( empty( $this->messages ) ) $this->messages = array(
26  'err_general' => 'GTicket Error' ,
27  'err_nostubs' => 'No stubs found' ,
28  'err_noticket' => 'No ticket found' ,
29  'err_nopair' => 'No valid ticket-stub pair found' ,
30  'err_timeout' => 'Time out' ,
31  'err_areaorref' => 'Invalid area or referer' ,
32  '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?' ,
33  'btn_repost' => 'repost' ,
34  ) ;
35  }
36 
37  // render form as plain html
38  function getTicketHtml( $salt = '' , $timeout = 1800 , $area = '' )
39  {
40  return '<input type="hidden" name="XOOPS_G_TICKET" value="'.$this->issue( $salt , $timeout , $area ).'" />' ;
41  }
42 
43  // returns an object of XoopsFormHidden including theh ticket
44  function getTicketXoopsForm( $salt = '' , $timeout = 1800 , $area = '' )
45  {
46  return new XoopsFormHidden( 'XOOPS_G_TICKET' , $this->issue( $salt , $timeout , $area ) ) ;
47  }
48 
49  // add a ticket as Hidden Element into XoopsForm
50  function addTicketXoopsFormElement( &$form , $salt = '' , $timeout = 1800 , $area = '' )
51  {
52  $form->addElement( new XoopsFormHidden( 'XOOPS_G_TICKET' , $this->issue( $salt , $timeout , $area ) ) ) ;
53  }
54 
55  // returns an array for xoops_confirm() ;
56  function getTicketArray( $salt = '' , $timeout = 1800 , $area = '' )
57  {
58  return array( 'XOOPS_G_TICKET' => $this->issue( $salt , $timeout , $area ) ) ;
59  }
60 
61  // return GET parameter string.
62  function getTicketParamString( $salt = '' , $noamp = false , $timeout=1800 , $area = '' )
63  {
64  return ( $noamp ? '' : '&amp;' ) . 'XOOPS_G_TICKET=' . $this->issue( $salt, $timeout , $area ) ;
65  }
66 
67  // issue a ticket
68  function issue( $salt = '' , $timeout = 1800 , $area = '' )
69  {
70  global $xoopsModule ;
71 
72  // create a token
73  list( $usec , $sec ) = explode( " " , microtime() ) ;
74  $appendix_salt = empty( $_SERVER['PATH'] ) ? XOOPS_DB_NAME : $_SERVER['PATH'] ;
75  $token = crypt( $salt . $usec . $appendix_salt . $sec ) ;
76  $this->_latest_token = $token ;
77 
78  if( empty( $_SESSION['XOOPS_G_STUBS'] ) ) $_SESSION['XOOPS_G_STUBS'] = array() ;
79 
80  // limit max stubs 10
81  if( sizeof( $_SESSION['XOOPS_G_STUBS'] ) > 10 ) {
82  $_SESSION['XOOPS_G_STUBS'] = array_slice( $_SESSION['XOOPS_G_STUBS'] , -10 ) ;
83  }
84 
85  // record referer if browser send it
86  $referer = empty( $_SERVER['HTTP_REFERER'] ) ? '' : $_SERVER['REQUEST_URI'] ;
87 
88  // area as module's dirname
89  if( ! $area && is_object( @$xoopsModule ) ) {
90  $area = $xoopsModule->getVar('dirname') ;
91  }
92 
93  // store stub
94  $_SESSION['XOOPS_G_STUBS'][] = array(
95  'expire' => time() + $timeout ,
96  'referer' => $referer ,
97  'area' => $area ,
98  'token' => $token
99  ) ;
100 
101  // paid md5ed token as a ticket
102  return md5( $token . XOOPS_DB_PREFIX ) ;
103  }
104 
105  // check a ticket
106  function check( $post = true , $area = '' , $allow_repost = true )
107  {
108  global $xoopsModule ;
109 
110  $this->_errors = array() ;
111 
112  // CHECK: stubs are not stored in session
113  if( ! is_array(@$_SESSION['XOOPS_G_STUBS'])) {
114  $this->_errors[] = $this->messages['err_nostubs'] ;
115  $_SESSION['XOOPS_G_STUBS'] = array() ;
116  }
117 
118  // get key&val of the ticket from a user's query
119  $ticket = $post ? @$_POST['XOOPS_G_TICKET'] : @$_GET['XOOPS_G_TICKET'] ;
120 
121  // CHECK: no tickets found
122  if( empty( $ticket ) ) {
123  $this->_errors[] = $this->messages['err_noticket'] ;
124  }
125 
126  // gargage collection & find a right stub
127  $stubs_tmp = $_SESSION['XOOPS_G_STUBS'] ;
128  $_SESSION['XOOPS_G_STUBS'] = array() ;
129  foreach( $stubs_tmp as $stub ) {
130  // default lifetime 30min
131  if( $stub['expire'] >= time() ) {
132  if( md5( $stub['token'] . XOOPS_DB_PREFIX ) === $ticket ) {
133  $found_stub = $stub ;
134  } else {
135  // store the other valid stubs into session
136  $_SESSION['XOOPS_G_STUBS'][] = $stub ;
137  }
138  } else {
139  if( md5( $stub['token'] . XOOPS_DB_PREFIX ) === $ticket ) {
140  // not CSRF but Time-Out
141  $timeout_flag = true ;
142  }
143  }
144  }
145 
146  // CHECK: the right stub found or not
147  if( empty( $found_stub ) ) {
148  if( empty( $timeout_flag ) ) $this->_errors[] = $this->messages['err_nopair'] ;
149  else $this->_errors[] = $this->messages['err_timeout'] ;
150  } else {
151 
152  // set area if necessary
153  // area as module's dirname
154  if( ! $area && is_object( @$xoopsModule ) ) {
155  $area = $xoopsModule->getVar('dirname') ;
156  }
157 
158  // check area or referer
159  if( @$found_stub['area'] == $area ) $area_check = true ;
160  if( ! empty( $found_stub['referer'] ) && strstr( @$_SERVER['HTTP_REFERER'] , $found_stub['referer'] ) ) $referer_check = true ;
161 
162  if( empty( $area_check ) && empty( $referer_check ) ) { // loose
163  $this->_errors[] = $this->messages['err_areaorref'] ;
164  }
165  }
166 
167  if( ! empty( $this->_errors ) ) {
168  if( $allow_repost ) {
169  // repost form
170  $this->draw_repost_form( $area ) ;
171  exit ;
172  } else {
173  // failed
174  $this->clear() ;
175  return false ;
176  }
177  } else {
178  // all green
179  return true;
180  }
181  }
182 
183  // draw form for repost
184  function draw_repost_form( $area = '' )
185  {
186  // Notify which file is broken
187  if( headers_sent() ) {
188  restore_error_handler() ;
189  set_error_handler( array( &$this , 'errorHandler4FindOutput' ) ) ;
190  header( 'Dummy: for warning' ) ;
191  restore_error_handler() ;
192  exit ;
193  }
194 
195  error_reporting( 0 ) ;
196  while( ob_get_level() ) ob_end_clean() ;
197 
198  $table = '<table>' ;
199  $form = '<form action="?'.htmlspecialchars(@$_SERVER['QUERY_STRING'],ENT_QUOTES).'" method="post" >' ;
200  foreach( $_POST as $key => $val ) {
201  if( $key == 'XOOPS_G_TICKET' ) continue ;
202  if( get_magic_quotes_gpc() ) {
203  $key = stripslashes( $key ) ;
204  }
205  if( is_array( $val ) ) {
206  list( $tmp_table , $tmp_form ) = $this->extract_post_recursive( htmlspecialchars($key,ENT_QUOTES) , $val ) ;
207  $table .= $tmp_table ;
208  $form .= $tmp_form ;
209  } else {
210  if( get_magic_quotes_gpc() ) {
211  $val = stripslashes( $val ) ;
212  }
213  $table .= '<tr><th>'.htmlspecialchars($key,ENT_QUOTES).'</th><td>'.htmlspecialchars($val,ENT_QUOTES).'</td></tr>'."\n" ;
214  $form .= '<input type="hidden" name="'.htmlspecialchars($key,ENT_QUOTES).'" value="'.htmlspecialchars($val,ENT_QUOTES).'" />'."\n" ;
215  }
216  }
217  $table .= '</table>' ;
218  $form .= $this->getTicketHtml(__LINE__,300,$area).'<input type="submit" value="'.$this->messages['btn_repost'].'" /></form>' ;
219 
220  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>' ;
221  }
222 
223  function extract_post_recursive( $key_name , $tmp_array ) {
224  $table = '' ;
225  $form = '' ;
226  foreach( $tmp_array as $key => $val ) {
227  if( get_magic_quotes_gpc() ) {
228  $key = stripslashes( $key ) ;
229  }
230  if( is_array( $val ) ) {
231  list( $tmp_table , $tmp_form ) = $this->extract_post_recursive( $key_name.'['.htmlspecialchars($key,ENT_QUOTES).']' , $val ) ;
232  $table .= $tmp_table ;
233  $form .= $tmp_form ;
234  } else {
235  if( get_magic_quotes_gpc() ) {
236  $val = stripslashes( $val ) ;
237  }
238  $table .= '<tr><th>'.$key_name.'['.htmlspecialchars($key,ENT_QUOTES).']</th><td>'.htmlspecialchars($val,ENT_QUOTES).'</td></tr>'."\n" ;
239  $form .= '<input type="hidden" name="'.$key_name.'['.htmlspecialchars($key,ENT_QUOTES).']" value="'.htmlspecialchars($val,ENT_QUOTES).'" />'."\n" ;
240  }
241  }
242  return array( $table , $form ) ;
243  }
244 
245 
246  // clear all stubs
247  function clear()
248  {
249  $_SESSION['XOOPS_G_STUBS'] = array() ;
250  }
251 
252 
253  // Ticket Using
254  function using()
255  {
256  if( ! empty( $_SESSION['XOOPS_G_STUBS'] ) ) {
257  return true;
258  } else {
259  return false;
260  }
261  }
262 
263 
264  // return errors
265  function getErrors( $ashtml = true )
266  {
267  if( $ashtml ) {
268  $ret = '' ;
269  foreach( $this->_errors as $msg ) {
270  $ret .= "$msg<br />\n" ;
271  }
272  } else {
273  $ret = $this->_errors ;
274  }
275  return $ret ;
276  }
277 
278  function errorHandler4FindOutput($errNo, $errStr, $errFile, $errLine)
279  {
280  if( preg_match( '?'.preg_quote(XOOPS_ROOT_PATH).'([^:]+)\:(\d+)?' , $errStr , $regs ) ) {
281  echo "Irregular output! check the file ".htmlspecialchars($regs[1])." line ".htmlspecialchars($regs[2]) ;
282  } else {
283  echo "Irregular output! check language files etc." ;
284  }
285  return ;
286  }
287 // end of class
288 }
289 
290 // create a instance in global scope
291 $GLOBALS['xoopsGTicket'] = new XoopsGTicket() ;
292 
293 }
294 
295 if( ! function_exists( 'admin_refcheck' ) ) {
296 
297 //Admin Referer Check By Marijuana(Rev.011)
298 function admin_refcheck($chkref = "") {
299  if( empty( $_SERVER['HTTP_REFERER'] ) ) {
300  return true ;
301  } else {
302  $ref = $_SERVER['HTTP_REFERER'];
303  }
304  $cr = XOOPS_URL;
305  if ( $chkref != "" ) { $cr .= $chkref; }
306  if ( strpos($ref, $cr) !== 0 ) { return false; }
307  return true;
308 }
309 
310 }
311 
312 
313 ?>