?$~i'; //John D. $rxEML = '~(^|\s)([^@\s]{2,40})@((?:[^@\s\.]{2,30}\.)*[^@\s\.]{2,30}).(\w{2,6})(?:\s*\[([^<>\[]+?)\])?(\.|\s|<|$)~im'; //jd@skyweb.com [title] $rxELink = "~]+>([^<>]+)~i"; //... $rxULink = '~]*?href=["\'](https?://([^|<>\s]{5,}))["\'][^|<>]*?>([^|<>]*?)~i'; //title $rxURL = '~(^|\s)(https?://)([^\s\[\<$]{5,}[^.\s\[\<$])(?:\s*\[([^<>\[]+?)\])?(\.|\s|<|$)~im'; //http://www.mysite.xxx [title] $rxCalURL = '~^(https?://)?((?:[\w-:]+\.)+[a-z]{2,15}(?:[/?#:][^<>\s\[]*)?|[\w-]{2,10}host(?::[0-9]{1,3})?|(?:[0-9]{1,3}\.){3}[0-9]{1,3})(/[^<>\s\[]+)*/?$~i'; //http://XXX/mycal/calendar.php (XXX = www.mysite.xxx | ?????host:70 | ip address) $rxPhone = '~^[+\d\s-/()]{6,20}$~'; //+1-541-754-3010, (089) / 636-48018, etc. $rxIMGTags = '~~i'; // $rxIMG = '~(?:^|\s)(([^\s/.]*/)*([^\s/.]+\.(?:gif|jpg|png)))(?:\.|\s|$)~i'; //thumbnails/mynail.gif (or .jpg, or .png) /*---------- TOOLBOX FUNCTIONS ----------*/ function mbtrunc($string,$length) { //multi-byte utf-8 truncate on char boundary if (strlen($string) <= $length) { return $string; } $ordNext = ord($string[$length]); if ($ordNext <= 127 or $ordNext >= 194) { return substr($string,0,$length); } //next byte is single byte or 1st byte of mb for ($i = ($length - 1); $i >= 0; $i--) { if (ord($string[$i]) <= 127) { return substr($string,0,$i+1); } //single byte if (ord($string[$i]) >= 194) { return substr($string,0,$i); } //1st byte of mb } return ''; //empty } function eol2txt($string) { //replace \n\r characters by {nl} and by \n return preg_replace(array("~[\n\r]+~","~~"),array("{nl}","\n "),trim($string)); } //Time formatting function ITtoDT($time,$format = '') { //convert hh:mm(:ss) to display time global $set; if (!$time) { return ''; } if (!$format) { $format = $set['timeFormat']; } $ampm = stripos($format,'a') !== false; if ($ampm and substr($time,0,2) =='24') { $time = '12'.substr($time,2); } $phpFormat = str_replace(array('H','h','m'),array(($ampm ? 'h' : 'H'),($ampm ? 'g' : 'G'),'i'),$format); return date($phpFormat,strtotime($time)); } function DTtoIT($time,$format = '') { //convert Display Time to ISO Time hh:mm global $set; $time = trim($time); if (!$time) { return ''; } if (!$format) { $format = $set['timeFormat']; } $ampm = stripos($format,'a') !== false; $regEx = $ampm ? '(0{0,1}[0-9]|1[0-2])[:.][0-5][0-9]\s*(a|A|p|P)(m|M)' : '(0{0,1}[0-9]|1[0-9]|2[0-4])[:.][0-5][0-9]([:.][0-5][0-9]){0,1}'; if (!preg_match("%^".$regEx."$%",$time)) { return false; } $tStamp = strtotime($time); return ($tStamp < 1) ? false : date("H:i", $tStamp); } //Date formatting function IDtoDD($date,$format = '') { //convert ISO date (yyyy mm dd) to display date global $set; if (!$date) { return ''; } if (!$format) { $format = $set['dateFormat']; } return str_replace(array('y','m','d'),array(substr($date,0,4),substr($date,5,2),substr($date,8,2)),$format); } function IDTtoDDT($dateTime) { //convert ISO date+time (yyyy mm dd hh:mm:ss) to display date global $xx; $date = substr($dateTime,0,10); if (!$date) { return ''; } $time = substr($dateTime,11,5); $dD = IDtoDD($date); $dT = ITtoDT($time); return $dD.($dT ? " {$xx['at_time']} {$dT}" : ''); } function DDtoID($date,$format = '') { //validate display date and convert to ISO date (yyyy-mm-dd) global $set; $date = trim($date); if (!$date) { return ''; } if (!$format) { $format = $set['dateFormat']; } $indexY = strpos($format,'y') / 2; $indexM = strpos($format,'m') / 2; $indexD = strpos($format,'d') / 2; $split = preg_split('%[^\d]%',$date); if ($split[$indexY] < 1900 or $split[$indexY] > 2099) { return false; } //year out of range if (!checkdate(intval($split[$indexM]),intval($split[$indexD]),intval($split[$indexY]))) { return false; } //invalid date return $split[$indexY]."-".str_pad($split[$indexM], 2, "0", STR_PAD_LEFT)."-".str_pad($split[$indexD], 2, "0", STR_PAD_LEFT); } function makeD($date,$formatNr,$x3 = '') { //make long date global $set, $months, $months_m, $wkDays, $wkDays_l; $y = substr($date, 0, 4); $m = ltrim(substr($date, 5, 2),"0"); $d = ltrim(substr($date, 8, 2),"0"); if ($formatNr > 3) { $wdNr = date("N", mktime(12,0,0,$m,$d,$y)); $wkDay = $x3 ? $wkDays_l[$wdNr] : $wkDays[$wdNr]; } $month = $x3 ? $months_m[$m - 1] : $months[$m - 1]; switch ($formatNr) { case 1: //Dec... 9 / 9 dec... return str_replace(array('d','M'),array($d,$month),$set['MdFormat']); case 2: //Dec... 9, 2018 / 9 dec... 2018 return str_replace(array('d','y','M'),array($d,$y,$month),$set['MdyFormat']); case 3: //Dec... 2018 / dec... 2018 return str_replace(array('y','M'),array($y,$month),$set['MyFormat']); case 4: //Mon..., Dec... 9 / mon 9 dec return str_replace(array('d','M','WD'),array($d,$month,$wkDay),$set['DMdFormat']); case 5: //Mon..., Dec... 9, 2018 / mon... 9 dec... 2018 return str_replace(array('d','y','M','WD'),array($d,$y,$month,$wkDay),$set['DMdyFormat']); } } function makeFullDT($iso,$sda,$eda,$sti,$eti) { //make full date/time global $xx; $fullDT = $iso ? IDtoDD($sda) : $sda; if ($sti) { $fullDT .= " {$xx['at_time']} ".($iso ? ITtoDT($sti) : $sti); } if ($eda or $eti) { $fullDT .= ' -'; } if ($eda) { $fullDT .= ' '.($iso ? IDtoDD($eda) : $eda).($eti ? " {$xx['at_time']}" : ''); } if ($eti) { $fullDT .= ' '.($iso ? ITtoDT($eti) : $eti); } if (!$sti and !$eti) { $fullDT .= " {$xx['vws_all_day']}"; } return $fullDT; } function makeHovT(&$evt) { //make hover box time switch ($evt['mde']) { //multi-day event? case 0: return ITtoDT($evt['sti']).($evt['eti'] ? ' - '.ITtoDT($evt['eti']) : ''); //no case 1: return (($evt['sti'] != '00:00' and $evt['sti'] != '') ? ITtoDT($evt['sti']) : '•').'···'; //first case 2: return '···'; //in between case 3: return '···'.(($evt['eti'] < '23:59' and $evt['eti'] != '') ? ITtoDT($evt['eti']) : '•'); //last } } function repeatText($type,$interval,$period,$rmonth,$until) { //make repeat text global $xx, $months, $wkDays; switch ($type) { case -1: $repTxt = "{$xx['evt_repeat_not_supported']}"; break; case 0: $repTxt = ''; break; case 1: $repTxt = $xx['evt_repeat_on'].' '.$interval.' '.$xx['evt_period1_'.$period]; break; case 2: $repTxt = $xx['evt_repeat_on'].' '.$xx['evt_interval2_'.$interval].' '.$wkDays[$period].' '.$xx['of'].' '.($rmonth ? $months[$rmonth-1] : $xx['evt_each_month']); } if ($type > 0 and $until and $until[0] != 9) { $repTxt .= " {$xx['evt_until']} ".IDtoDD($until); } return $repTxt; } function makeE(&$evt,$template,$type,$glue,$show = '12345678') { //make event body using template global $set, $usr, $xx; if (!$set['xField1Public'] and $usr['ID'] == 1) { $show = str_replace('4','',$show); } //exclude xField 1 if (!$set['xField2Public'] and $usr['ID'] == 1) { $show = str_replace('5','',$show); } //exclude xField 2 $eArray = array(); if ($type[0] == 'b') { //type br foreach (str_split($template) as $fieldNr) { if (strpos($show,$fieldNr) === false) { continue; } switch ($fieldNr) { case '1': if ($evt['ven']) { $eArray[] = "{$xx['evt_venue']}: {$evt['ven']}"; } break; case '2': $eArray[] = "{$xx['evt_category']}: {$evt['cnm']}".($evt['snm'] ? " - {$evt['snm']}" : ''); break; case '3': if ($evt['des']) { $eArray[] = $type[1] == 'x' ? hyperImg($evt['des']) : $evt['des']; } break; case '4': if ($evt['xf1']) { $eArray[] = ($set['xField1Label'] ? "{$set['xField1Label']}: " : '').($type[1] == 'x' ? hyperImg($evt['xf1']) : $evt['xf1']); } break; case '5': if ($evt['xf2']) { $eArray[] = ($set['xField2Label'] ? "{$set['xField2Label']}: " : '').($type[1] == 'x' ? hyperImg($evt['xf2']) : $evt['xf2']); } break; case '6': if ($evt['nom'] >= 0) { $eArray[] = "{$xx['vws_notify']}: {$evt['nom']} {$xx['vws_days']}"; } break; if ($evt['nos'] >= 0) { $eArray[] = "{$xx['vws_notify']}: {$evt['nos']} {$xx['vws_days']}"; } break; case '7': $eArray[] = "{$xx['vws_added']}: ".IDTtoDDT($evt['adt'])." ({$evt['una']})"; if ($evt['mdt'] and $evt['edr']) { $eArray[] = "{$xx['vws_edited']}: ".IDTtoDDT($evt['mdt'])." ({$evt['edr']})"; } break; case '8': if ($evt['att']) { $attachments = array(); foreach(explode(';',trim($evt['att'],';')) as $attachment) { $attachments[] = "".substr($attachment,14).""; } $eArray[] = $xx['evt_attachments'].': '.implode(', ',$attachments); } } } } else { //type td foreach (str_split($template) as $fieldNr) { if (strpos($show,$fieldNr) === false) { continue; } switch ($fieldNr) { case '1': if ($evt['ven']) { $eArray[] = "{$xx['evt_venue']}:{$evt['ven']}"; } break; case '2': $eArray[] = "{$xx['evt_category']}:{$evt['cnm']}".($evt['snm'] ? " - {$evt['snm']}" : '').""; break; case '3': if ($evt['des']) { $eArray[] = "{$xx['evt_description']}:".($type[1] == 'x' ? hyperImg($evt['des']) : $evt['des']).""; } break; case '4': if ($evt['xf1']) { $eArray[] = "".($set['xField1Label'] ? "{$set['xField1Label']}: " : '')."".($type[1] == 'x' ? hyperImg($evt['xf1']) : $evt['xf1']).""; } break; case '5': if ($evt['xf2']) { $eArray[] = "".($set['xField2Label'] ? "{$set['xField2Label']}: " : '')."".($type[1] == 'x' ? hyperImg($evt['xf2']) : $evt['xf2']).""; } break; case '6': if ($evt['nom'] >= 0) { $eArray[] = "{$xx['vws_notify']}:{$evt['nom']} {$xx['vws_days']}"; } break; if ($evt['nos'] >= 0) { $eArray[] = "{$xx['vws_notify']}:{$evt['nos']} {$xx['vws_days']}"; } break; case '7': $eArray[] = "{$xx['vws_added']}:".IDTtoDDT($evt['adt'])." ({$evt['una']})"; if ($evt['mdt'] and $evt['edr']) { $eArray[] = "{$xx['vws_edited']}:".IDTtoDDT($evt['mdt'])." ({$evt['edr']})"; } break; case '8': if ($evt['att']) { $label = $xx['evt_attachments'].':'; foreach(explode(';',trim($evt['att'],';')) as $attachment) { $eArray[] = "{$label}".substr($attachment,14).""; $label = ''; } } } } } return implode($glue,$eArray); } // //Check on overlap. For recurring events look ahead $chkYears years // function overlap($eid,$cid,$sDate,$eDate,$sTime,$eTime,$catRpt,$r_t,$r_i,$r_p,$r_m,$r_u) { //check for no overlap global $evtList, $usr; //Number of years to look ahead for overlaps $chkYears = 2; //prepare overlap test $filter = "((c.`noverlap` = 1 AND c.`ID` = $cid) OR c.`noverlap` = 2)".($eid ? " AND e.`ID` != {$eid}" : ''); //if update, exclude event self $usrPrivs = $usr['privs']; //set privs temporary to admin to catch all events $usr['privs'] = 9; $dUts = ($eDate[0] != '9') ? strtotime($eDate) - strtotime($sDate) : 0; //delta start date - end date uts if ($eTime[1] == '9') { $eTime = $sTime; } //no end time if ($catRpt > 0) { //cat repeat overrides $r_t = $r_i = 1; $r_p = $catRpt; $r_u = '9999-00-00'; } if ($r_t == 2) { $sDate = nextRdate2($sDate,$r_i,$r_p,$r_m,0); //1st occurrence of xth in month y } //now $sDate is the first date for $r_t = 0, 1 or 2 $eDate = $dUts > 0 ? date("Y-m-d",strtotime($sDate) + $dUts) : $sDate; if (!$r_u) { $r_u = '9999-00-00'; } $uDate = min($r_u,date("Y-m-d",time() + (32000000 * $chkYears))); //check until date ($r_u or $lookAhead years) $oDate = $oMsg = ''; do { //retrieve 'no-overlap' events in same date/time bracket $sTimeNew = strtotime($sDate.' '.$sTime.':00'); $eTimeNew = strtotime($eDate.' '.$eTime.':00'); retrieve($sDate,$eDate,'',$filter); //overlap check foreach ($evtList as $date => $calEvts) { foreach ($calEvts as $evt) { //check events on this day $sTimeC = ($evt['sti'] and $evt['mde'] < 2) ? $evt['sti'] : '00:00'; $eTimeC = ($evt['eti'] and $evt['mde'] != 1 and $evt['mde'] != 2) ? $evt['eti'] : '23:59'; $sTimeCal = strtotime($date.' '.$sTimeC.':00'); $eTimeCal = strtotime($date.' '.$eTimeC.':00'); if (($sTimeNew >= $sTimeCal and $sTimeNew < ($eTimeCal + ($evt['olg'] * 60))) or ($sTimeCal >= $sTimeNew and $sTimeCal < ($eTimeNew + ($evt['olg'] * 60)))) { $oMsg = $evt['oem']; //overlap error message $oDate = $date; break 3; } } } if ($r_t > 0) { $sDate = ($r_t == 1) ? nextRdate1($sDate,$r_i,$r_p) : nextRdate2($sDate,$r_i,$r_p,$r_m,1); $eDate = date("Y-m-d",strtotime($sDate) + $dUts); } } while ($r_t > 0 and $sDate < $uDate); $usr['privs'] = $usrPrivs; //restore privs return $oMsg ? IDtoDD($oDate).': '.$oMsg : ''; } // //Compute next event start date - repeat every xth ($rI) day, week, month or year ($rP) // function nextRdate1($curD, $rI, $rP) { $curT = strtotime($curD.' 12:00:00'); $curDoM = date('j',$curT); switch ($rP) { //period case 1: //day $nUts = strtotime("+$rI days",$curT); break; case 2: //week $nUts = strtotime("+$rI weeks",$curT); break; case 3: //month $i = 1; while(date('j',strtotime('+'.$i*$rI.' months',$curT)) != $curDoM) { $i++; } //deal with 31st $nUts = strtotime('+'.$i*$rI.' months',$curT); break; case 4: //year $i = 1; while(date('j',strtotime('+'.$i*$rI.' years',$curT)) != $curDoM) { $i++; } //deal with 29/02 $nUts = strtotime('+'.$i*$rI.' years',$curT); break; } return date("Y-m-d",$nUts); } // //Compute next event start date - repeat on the xth ($rI) ($rP) of month y ($rM) // function nextRdate2($curD, $rI, $rP, $rM, $i) { //$i=0: 1st occurrence; $i=1: next occurrence if ($rM) { $curM = $rM; //one specific month $curY = substr($curD,0,4)+$i+((substr($curD,5,2) <= $rM) ? 0 : 1); } else { //each month $curM = substr($curD,5,2)+$i; $curY = substr($curD,0,4); } $day1Ts = mktime(12,0,0,$curM,1,$curY); $dowDif = $rP - date('N',$day1Ts); //day of week difference $offset = $dowDif + 7 * $rI; if ($dowDif >= 0) { $offset -= 7; } if ($offset >= date('t',$day1Ts)) { $offset -= 7; } //'t': number of days in the month return date("Y-m-d",$day1Ts + (86400 * $offset)); } //expand images to image hyperlinks function hyperImg($text) { global $rxIMGTags; return preg_replace($rxIMGTags,"$0",$text); } //get calendar base URL (used at install) function calBaseUrl() { $baseUrl = 'http'.(!empty($_SERVER['HTTPS']) ? 's' : '').'://'.$_SERVER['SERVER_NAME']; if ($_SERVER["SERVER_PORT"] != '80') { $baseUrl .= ':'.$_SERVER['SERVER_PORT']; } $baseUrl .= rtrim(dirname($_SERVER["PHP_SELF"]),'/').'/'; // add calendar directory return $baseUrl; } //get calendar root URL function calRootUrl() { global $set; $rootUrl = strstr($set['calendarUrl'].'?','?',true); $rootUrl = strstr($rootUrl.'/index.php','/index.php',true); return rtrim($rootUrl,'/').'/'; } //add URL, IMG and EML links function addUrlImgEmlTags($html,$uie='xxx') { global $set, $rxURL, $rxIMG, $rxEML, $xx; if ($uie[0] == 'x') { //create URL links $html = preg_replace_callback($rxURL,function ($m) { return "{$m[1]}".(!empty($m[4])?$m[4]:$m[3])."{$m[5]}"; },$html); } if ($uie[1] == 'x') { //create image links $html = preg_replace_callback($rxIMG,function ($m) { return " {$m[3]}"; },$html); } if ($uie[2] == 'x') { //create email links $html = preg_replace_callback($rxEML,function ($m) { global $tit, $xx; return "{$m[1]}".(!empty($m[5])?$m[5]:$xx['vws_send_mail'])."{$m[6]}"; },$html); } return $html; } //remove URL, IMG and EML links function remUrlImgEmlTags($html,$uie='xxx') { global $rxULink, $rxIMGTags, $rxELink; if ($uie[0] == 'x') { //remove URL links $html = preg_replace_callback($rxULink,function ($m) { return $m[1].($m[2]!=$m[3]?" [".$m[3]."]":""); },$html); } if ($uie[1] == 'x') { //remove image links $html = preg_replace($rxIMGTags,"$1 ",$html); } if ($uie[2] == 'x') { //remove email links $html = preg_replace($rxELink,"$1@$2.$3 [$4]",$html); } return $html; } //chunk split unicode string function chunk_split_unicode($str,$len,$eol) { $chunks = array_chunk(preg_split('%%u',$str,-1,PREG_SPLIT_NO_EMPTY),$len); $str = ''; foreach ($chunks as $chunk) { $str .= implode($chunk).$eol; } return rtrim($str); } //transliterate text string (e.g. file name) function translit($text,$strict=false) { setlocale(LC_CTYPE,'en_US'); $transText = iconv('UTF-8','ASCII//TRANSLIT',$text); if ($strict) { return str_replace(array(' ','/','\\','?','%','*',':',';','{','}',"'",'"'),'_',$transText); } else { return $transText; } } //validate index.php vars function validVars() { $passed = true; foreach ($_GET as $key => $value) { switch ($key) { case 'cal': $passed = preg_match('~^\w{1,20}?$~',$value); break; case 'cP': $passed = preg_match('~^(\d{1,3}|up)$~',$value); break; case 'cG': $passed = (is_array($value) and ctype_digit(implode($value))); break; case 'cU': $passed = (is_array($value) and ctype_digit(implode($value))); break; case 'cC': $passed = (is_array($value) and ctype_digit(implode($value))); break; case 'cL': $passed = empty($value) ? true : preg_match('~^[a-zA-Z]{1,12}$~',$value); break; case 'cD': $passed = empty($value) ? true : preg_match('~^\d{4}-\d{2}-\d{2}$~',$value); break; case 'hdr': $passed = preg_match('~^(0|1|-1|-2)$~',$value); break; default: if (is_string($value)) $_GET[$key] = htmlspecialchars(strip_tags(trim($value)),ENT_QUOTES,'UTF-8'); } if (!$passed) { logMessage('luxcal',2,'Access denied. Invalid GET variable ('.$key.'='.htmlspecialchars($value,ENT_QUOTES,'UTF-8').')'); exit('not permitted (index.php - invalid var: '.$key.')'); } } if (!empty($_POST)) { //validate POST vars $error = empty($_POST['lcI']) ? 'Not permitted - CSRF
No PT' : ($_POST['lcI'] == 'i' ? '' : (empty($_SESSION['lcI']) ? 'Session expired - Please restart the calendar.
No ST' : ($_SESSION['lcI'] != $_POST['lcI'] ? 'Not permitted - CSRF
Invalid PT' : ''))); if ($error) { logMessage('luxcal',2,"Access denied. Spoofed form submission detected.\nForm input keys:\n- ".implode("\n- ",array_keys($_POST))); unset($_SESSION['lcI']); exit($error); } foreach ($_POST as $key => $value) { if (is_string($value)) { $_POST[$key] = strip_tags(trim($value),'
'); } } } } //log message function logMessage($logName,$level,$logMsg,$script='-') { global $set; $levels = array(0 => 'CRONJOB','ERROR','WARNING','NOTICE'); if ($level < 2 or ($level == 2 and $set['logWarnings']) or ($level == 3 and $set['logNotices'])) { date_default_timezone_set(@date_default_timezone_get()); if ($script == '-') { $script = $_SERVER['PHP_SELF']; } $intro = "\n".date('Y.m.d H:i:s')." {$levels[$level]} Script: ".htmlentities($script); file_put_contents("./logs/{$logName}.log","{$intro} - {$logMsg}",FILE_APPEND); } } //save selections to cookie LCALsel_ function saveLastSel($calID,$calPath) { global $set, $opt; if (!empty($_SESSION)) { $lastSel = array('cP' => $opt['cP'],'cG' => $opt['cG'],'cU' => $opt['cU'],'cC' => $opt['cC'],'cL' => $opt['cL']); setcookie("LCALsel_{$calID}", serialize($lastSel), time()+(86400 * $set['cookieExp']),$calPath); //keep data for 'cookieExp' days } } //load selections from cookie LCALsel_ function loadLastSel($calID) { $lastSel = isset($_COOKIE["LCALsel_{$calID}"]) ? @unserialize($_COOKIE["LCALsel_{$calID}"]) : false; if ($lastSel) { $_SESSION['cP'] = $lastSel['cP']; $_SESSION['cG'] = isset($lastSel['cG']) ? $lastSel['cG'] : array(0); //cG in cookie as of V4.3 $_SESSION['cU'] = $lastSel['cU']; $_SESSION['cC'] = $lastSel['cC']; $_SESSION['cL'] = $lastSel['cL']; } } //check for mobile browser (returns 0: not mobile, 1: tablet or 2: mobile small screen size) function isMobile() { $userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : ''; $mobileAgents = array( 'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac', 'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno', 'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-', 'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-', 'newt','noki','oper','palm','pana','pant','phil','play','port','prox', 'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar', 'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-', 'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp', 'wapr','webc','winw','winw','xda','xda-' ); if (preg_match('%(tablet|ipad|playbook)|(android(?!.*(mobi|opera mini)))%', $userAgent)) { return 1; //mobile but tablet } if (preg_match('%(symbian|midp|mobile|phone|ipod|android)%',$userAgent)) { return 2; //mobile } elseif ((!empty($_SERVER['HTTP_ACCEPT'])) and (strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false)) { return 2; //mobile } elseif (in_array((substr($userAgent,0,4)),$mobileAgents)) { return 2; //mobile } return 0; } ?>