Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F120822628
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
7 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/Kolab/FreeBusy/Utils.php b/lib/Kolab/FreeBusy/Utils.php
index c045963..15dde17 100644
--- a/lib/Kolab/FreeBusy/Utils.php
+++ b/lib/Kolab/FreeBusy/Utils.php
@@ -1,274 +1,280 @@
<?php
/**
* This file is part of the Kolab Server Free/Busy Service
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2013-2014, Kolab Systems AG <contact@kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Kolab\FreeBusy;
/**
* Static calss providing utility functions for the Free/Busy service
*/
class Utils
{
const PRODID = '-//kolab.org//NONSGML Kolab Free-Busy Service 3.2//EN';
/**
* Resolve the given directory to a real path ending with $append
*
* @param string Arbitrary directory directory path
* @param string Make path end with this string/character
* @return string Absolute file system path
*/
public static function abspath($dirname, $append = '')
{
if ($dirname[0] != '/')
$dirname = realpath(KOLAB_FREEBUSY_ROOT . '/' . $dirname);
return rtrim($dirname, '/') . $append;
}
/**
* Returns remote IP address and forwarded addresses if found
*
* @return string Remote IP address(es)
*/
public static function remoteIP()
{
$address = $_SERVER['REMOTE_ADDR'];
// use the NGINX X-Real-IP header, if set
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
$address = $_SERVER['HTTP_X_REAL_IP'];
}
// use the X-Forwarded-For header, if set
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$address = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
return $address;
}
/**
* Checks if the given IP address is in one of the provided ranges
*
* @param string IP address
* @param array List of IP ranges/subnets to check against
* @return boolean True if in range, False if not
*/
public static function checkIPRange($ip, $ranges)
{
$ipv6 = strpos($ip, ':') !== false;
$ipbin = $ipv6 ? self::ip6net2bits($ip) : ip2long($ip);
foreach ((array)$ranges as $range) {
// don't compare IPv4 and IPv6 addresses/ranges
$rangev6 = strpos($range, ':') !== false;
if ($ipv6 != $rangev6) {
continue;
}
+ // special entries that allow all IPs
+ if ($range === '*' || $range === 'all' || $range === '0/0'
+ || $range === '0.0.0.0/0' || $range === '0.0.0.0/0.0.0.0') {
+ return true;
+ }
+
// quick substring check (e.g. 192.168.0.)
if (( $ipv6 && strpos($ipbin, self::ip6net2bits($range)) === 0) ||
(!$ipv6 && strpos($ip, rtrim($range, '*')) === 0)) {
return true;
}
// range from-to specified (IPv4 only)
list($lower, $upper) = explode('-', $range);
if (strlen($upper) && !$ipv6) {
if ($ipbin >= ip2long(trim($lower)) && $ipbin <= ip2long(trim($upper))) {
return true;
}
}
// subnet/length is given
list($subnet, $bits) = explode('/', $range);
// IPv6 subnet
if (strlen($bits) && $ipv6) {
$subnetbin = self::ip6net2bits($subnet);
if (substr($ipbin, 0, $bits) === substr($subnetbin, 0, $bits)) {
return true;
}
}
// IPv4 subnet
else if (strlen($bits)) {
$subnet = ip2long($subnet);
$mask = -1 << $bits;
$subnet &= $mask; // just in case the supplied subnet wasn't correctly aligned
if (($ipbin & $mask) == $subnet) {
return true;
}
}
}
return false;
}
/**
* Convert the given IPv6 address to a binary string representation.
* (from http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet)
*/
public static function ip6net2bits($inet)
{
$binaryip = '';
$unpacked = @unpack('A16', inet_pton($inet));
foreach (str_split($unpacked[1]) as $char) {
$binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT);
}
return $binaryip;
}
/**
* Returns number of seconds for a specified offset string.
*
* @param string String representation of the offset (e.g. 20min, 5h, 2days, 1week)
* @return int Number of seconds
*/
public static function getOffsetSec($str)
{
if (preg_match('/^([0-9]+)\s*([smhdw])/i', $str, $regs)) {
$amount = (int) $regs[1];
$unit = strtolower($regs[2]);
}
else {
$amount = (int) $str;
$unit = 's';
}
switch ($unit) {
case 'w':
$amount *= 7;
case 'd':
$amount *= 24;
case 'h':
$amount *= 60;
case 'm':
$amount *= 60;
}
return $amount;
}
/**
* Getter for the free/busy period start time
*
* @return int Unix timestamp
*/
public static function periodStart()
{
// use date from HTTP query
if (!empty($_GET['dtstart'])) {
return self::periodStartDT()->format('U');
}
// Should probably be a setting. For now, do 8 weeks in the past
return time() - (60 * 60 * 24 * 7 * 8);
}
/**
* Getter for the free/busy period start time
*
* @return object DateTime instance
*/
public static function periodStartDT()
{
// use date from HTTP query
if (!empty($_GET['dtstart']) &&
($dtstart = filter_input(INPUT_GET, 'dtstart', FILTER_SANITIZE_STRING))
) {
try {
return new \DateTime($dtstart, new \DateTimezone('UTC'));
}
catch (Exception $e) {
// ignore
}
}
// Should probably be a setting. For now, do 8 weeks in the past
return new \DateTime('now - 8 weeks 00:00:00', new \DateTimezone('UTC'));
}
/**
* Getter for the free/busy period end time
*
* @return int Unix timestamp
*/
public static function periodEnd()
{
// use date from HTTP query
if (!empty($_GET['dtend'])) {
return self::periodEndDT()->format('U');
}
// Should probably be a setting. For now, do 16 weeks into the future
return time() + (60 * 60 * 24 * 7 * 16);
}
/**
* Getter for the free/busy period end time
*
* @return object DateTime instance
*/
public static function periodEndDT()
{
// use date from HTTP query
if (!empty($_GET['dtend']) &&
($dtend = filter_input(INPUT_GET, 'dtend', FILTER_SANITIZE_STRING))
) {
try {
return new \DateTime($dtend, new \DateTimezone('UTC'));
}
catch (Exception $e) {
// ignore
}
}
// Should probably be a setting. For now, do 8 weeks in the past
return new \DateTime('now + 16 weeks 00:00:00', new \DateTimezone('UTC'));
}
/**
* Returns an apparent empty Free/Busy list for the given user
*/
public static function dummyVFreebusy($user)
{
$now = time();
$dtformat = 'Ymd\THis\Z';
$dummy = "BEGIN:VCALENDAR\n";
$dummy .= "VERSION:2.0\n";
$dummy .= "PRODID:" . self::PRODID . "\n";
$dummy .= "METHOD:PUBLISH\n";
$dummy .= "BEGIN:VFREEBUSY\n";
$dummy .= "ORGANIZER:MAILTO:" . $user . "\n";
$dummy .= "DTSTAMP:" . gmdate($dtformat) . "\n";
$dummy .= "DTSTART:" . gmdate($dtformat, self::periodStart()) . "\n";
$dummy .= "DTEND:" . gmdate($dtformat, self::periodEnd()) . "\n";
$dummy .= "COMMENT:This is a dummy vfreebusy that indicates an empty calendar\n";
$dummy .= "FREEBUSY:19700101T000000Z/19700101T000000Z\n";
$dummy .= "END:VFREEBUSY\n";
$dummy .= "END:VCALENDAR\n";
return $dummy;
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Apr 24, 9:53 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18896474
Default Alt Text
(7 KB)
Attached To
Mode
rF freebusy
Attached
Detach File
Event Timeline