Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117884063
kolab_format.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
26 KB
Referenced Files
None
Subscribers
None
kolab_format.php
View Options
<?php
/**
* Kolab format model class wrapping libkolabxml bindings
*
* Abstract base class for different Kolab groupware objects read from/written
* to the new Kolab 3 format using the PHP bindings of libkolabxml.
*
* @version @package_version@
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
* Copyright (C) 2012, 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/>.
*/
abstract
class
kolab_format
{
public
static
$timezone
;
public
/*abstract*/
$CTYPE
;
public
/*abstract*/
$CTYPEv2
;
protected
/*abstract*/
$objclass
;
protected
/*abstract*/
$read_func
;
protected
/*abstract*/
$write_func
;
protected
$obj
;
protected
$data
;
protected
$xmldata
;
protected
$xmlobject
;
protected
$formaterror
;
protected
$loaded
=
false
;
protected
$version
=
'3.0'
;
const
KTYPE_PREFIX
=
'application/x-vnd.kolab.'
;
const
PRODUCT_ID
=
'Roundcube-libkolab-1.1'
;
// mapping table for valid PHP timezones not supported by libkolabxml
// basically the entire list of ftp://ftp.iana.org/tz/data/backward
protected
static
$timezone_map
=
array
(
'Africa/Asmera'
=>
'Africa/Asmara'
,
'Africa/Timbuktu'
=>
'Africa/Abidjan'
,
'America/Argentina/ComodRivadavia'
=>
'America/Argentina/Catamarca'
,
'America/Atka'
=>
'America/Adak'
,
'America/Buenos_Aires'
=>
'America/Argentina/Buenos_Aires'
,
'America/Catamarca'
=>
'America/Argentina/Catamarca'
,
'America/Coral_Harbour'
=>
'America/Atikokan'
,
'America/Cordoba'
=>
'America/Argentina/Cordoba'
,
'America/Ensenada'
=>
'America/Tijuana'
,
'America/Fort_Wayne'
=>
'America/Indiana/Indianapolis'
,
'America/Indianapolis'
=>
'America/Indiana/Indianapolis'
,
'America/Jujuy'
=>
'America/Argentina/Jujuy'
,
'America/Knox_IN'
=>
'America/Indiana/Knox'
,
'America/Louisville'
=>
'America/Kentucky/Louisville'
,
'America/Mendoza'
=>
'America/Argentina/Mendoza'
,
'America/Porto_Acre'
=>
'America/Rio_Branco'
,
'America/Rosario'
=>
'America/Argentina/Cordoba'
,
'America/Virgin'
=>
'America/Port_of_Spain'
,
'Asia/Ashkhabad'
=>
'Asia/Ashgabat'
,
'Asia/Calcutta'
=>
'Asia/Kolkata'
,
'Asia/Chungking'
=>
'Asia/Shanghai'
,
'Asia/Dacca'
=>
'Asia/Dhaka'
,
'Asia/Katmandu'
=>
'Asia/Kathmandu'
,
'Asia/Macao'
=>
'Asia/Macau'
,
'Asia/Saigon'
=>
'Asia/Ho_Chi_Minh'
,
'Asia/Tel_Aviv'
=>
'Asia/Jerusalem'
,
'Asia/Thimbu'
=>
'Asia/Thimphu'
,
'Asia/Ujung_Pandang'
=>
'Asia/Makassar'
,
'Asia/Ulan_Bator'
=>
'Asia/Ulaanbaatar'
,
'Atlantic/Faeroe'
=>
'Atlantic/Faroe'
,
'Atlantic/Jan_Mayen'
=>
'Europe/Oslo'
,
'Australia/ACT'
=>
'Australia/Sydney'
,
'Australia/Canberra'
=>
'Australia/Sydney'
,
'Australia/LHI'
=>
'Australia/Lord_Howe'
,
'Australia/NSW'
=>
'Australia/Sydney'
,
'Australia/North'
=>
'Australia/Darwin'
,
'Australia/Queensland'
=>
'Australia/Brisbane'
,
'Australia/South'
=>
'Australia/Adelaide'
,
'Australia/Tasmania'
=>
'Australia/Hobart'
,
'Australia/Victoria'
=>
'Australia/Melbourne'
,
'Australia/West'
=>
'Australia/Perth'
,
'Australia/Yancowinna'
=>
'Australia/Broken_Hill'
,
'Brazil/Acre'
=>
'America/Rio_Branco'
,
'Brazil/DeNoronha'
=>
'America/Noronha'
,
'Brazil/East'
=>
'America/Sao_Paulo'
,
'Brazil/West'
=>
'America/Manaus'
,
'Canada/Atlantic'
=>
'America/Halifax'
,
'Canada/Central'
=>
'America/Winnipeg'
,
'Canada/East-Saskatchewan'
=>
'America/Regina'
,
'Canada/Eastern'
=>
'America/Toronto'
,
'Canada/Mountain'
=>
'America/Edmonton'
,
'Canada/Newfoundland'
=>
'America/St_Johns'
,
'Canada/Pacific'
=>
'America/Vancouver'
,
'Canada/Saskatchewan'
=>
'America/Regina'
,
'Canada/Yukon'
=>
'America/Whitehorse'
,
'Chile/Continental'
=>
'America/Santiago'
,
'Chile/EasterIsland'
=>
'Pacific/Easter'
,
'Cuba'
=>
'America/Havana'
,
'Egypt'
=>
'Africa/Cairo'
,
'Eire'
=>
'Europe/Dublin'
,
'Europe/Belfast'
=>
'Europe/London'
,
'Europe/Tiraspol'
=>
'Europe/Chisinau'
,
'GB'
=>
'Europe/London'
,
'GB-Eire'
=>
'Europe/London'
,
'Greenwich'
=>
'Etc/GMT'
,
'Hongkong'
=>
'Asia/Hong_Kong'
,
'Iceland'
=>
'Atlantic/Reykjavik'
,
'Iran'
=>
'Asia/Tehran'
,
'Israel'
=>
'Asia/Jerusalem'
,
'Jamaica'
=>
'America/Jamaica'
,
'Japan'
=>
'Asia/Tokyo'
,
'Kwajalein'
=>
'Pacific/Kwajalein'
,
'Libya'
=>
'Africa/Tripoli'
,
'Mexico/BajaNorte'
=>
'America/Tijuana'
,
'Mexico/BajaSur'
=>
'America/Mazatlan'
,
'Mexico/General'
=>
'America/Mexico_City'
,
'NZ'
=>
'Pacific/Auckland'
,
'NZ-CHAT'
=>
'Pacific/Chatham'
,
'Navajo'
=>
'America/Denver'
,
'PRC'
=>
'Asia/Shanghai'
,
'Pacific/Ponape'
=>
'Pacific/Pohnpei'
,
'Pacific/Samoa'
=>
'Pacific/Pago_Pago'
,
'Pacific/Truk'
=>
'Pacific/Chuuk'
,
'Pacific/Yap'
=>
'Pacific/Chuuk'
,
'Poland'
=>
'Europe/Warsaw'
,
'Portugal'
=>
'Europe/Lisbon'
,
'ROC'
=>
'Asia/Taipei'
,
'ROK'
=>
'Asia/Seoul'
,
'Singapore'
=>
'Asia/Singapore'
,
'Turkey'
=>
'Europe/Istanbul'
,
'UCT'
=>
'Etc/UCT'
,
'US/Alaska'
=>
'America/Anchorage'
,
'US/Aleutian'
=>
'America/Adak'
,
'US/Arizona'
=>
'America/Phoenix'
,
'US/Central'
=>
'America/Chicago'
,
'US/East-Indiana'
=>
'America/Indiana/Indianapolis'
,
'US/Eastern'
=>
'America/New_York'
,
'US/Hawaii'
=>
'Pacific/Honolulu'
,
'US/Indiana-Starke'
=>
'America/Indiana/Knox'
,
'US/Michigan'
=>
'America/Detroit'
,
'US/Mountain'
=>
'America/Denver'
,
'US/Pacific'
=>
'America/Los_Angeles'
,
'US/Samoa'
=>
'Pacific/Pago_Pago'
,
'Universal'
=>
'Etc/UTC'
,
'W-SU'
=>
'Europe/Moscow'
,
'Zulu'
=>
'Etc/UTC'
,
);
/**
* Factory method to instantiate a kolab_format object of the given type and version
*
* @param string Object type to instantiate
* @param float Format version
* @param string Cached xml data to initialize with
* @return object kolab_format
*/
public
static
function
factory
(
$type
,
$version
=
'3.0'
,
$xmldata
=
null
)
{
if
(!
isset
(
self
::
$timezone
))
self
::
$timezone
=
new
DateTimeZone
(
'UTC'
);
if
(!
self
::
supports
(
$version
))
return
PEAR
::
raiseError
(
"No support for Kolab format version "
.
$version
);
$type
=
preg_replace
(
'/configuration
\.
[a-z._]+$/'
,
'configuration'
,
$type
);
$suffix
=
preg_replace
(
'/[^a-z]+/'
,
''
,
$type
);
$classname
=
'kolab_format_'
.
$suffix
;
if
(
class_exists
(
$classname
))
return
new
$classname
(
$xmldata
,
$version
);
return
PEAR
::
raiseError
(
"Failed to load Kolab Format wrapper for type "
.
$type
);
}
/**
* Determine support for the given format version
*
* @param float Format version to check
* @return boolean True if supported, False otherwise
*/
public
static
function
supports
(
$version
)
{
if
(
$version
==
'2.0'
)
return
class_exists
(
'kolabobject'
);
// default is version 3
return
class_exists
(
'kolabformat'
);
}
/**
* Convert the given date/time value into a cDateTime object
*
* @param mixed Date/Time value either as unix timestamp, date string or PHP DateTime object
* @param DateTimeZone The timezone the date/time is in. Use global default if Null, local time if False
* @param boolean True of the given date has no time component
* @return object The libkolabxml date/time object
*/
public
static
function
get_datetime
(
$datetime
,
$tz
=
null
,
$dateonly
=
false
)
{
// use timezone information from datetime of global setting
if
(!
$tz
&&
$tz
!==
false
)
{
if
(
$datetime
instanceof
DateTime
)
$tz
=
$datetime
->
getTimezone
();
if
(!
$tz
)
$tz
=
self
::
$timezone
;
}
$result
=
new
cDateTime
();
try
{
// got a unix timestamp (in UTC)
if
(
is_numeric
(
$datetime
))
{
$datetime
=
new
DateTime
(
'@'
.
$datetime
,
new
DateTimeZone
(
'UTC'
));
if
(
$tz
)
$datetime
->
setTimezone
(
$tz
);
}
else
if
(
is_string
(
$datetime
)
&&
strlen
(
$datetime
))
{
$datetime
=
$tz
?
new
DateTime
(
$datetime
,
$tz
)
:
new
DateTime
(
$datetime
);
}
}
catch
(
Exception
$e
)
{}
if
(
$datetime
instanceof
DateTime
)
{
$result
->
setDate
(
$datetime
->
format
(
'Y'
),
$datetime
->
format
(
'n'
),
$datetime
->
format
(
'j'
));
if
(!
$dateonly
)
$result
->
setTime
(
$datetime
->
format
(
'G'
),
$datetime
->
format
(
'i'
),
$datetime
->
format
(
's'
));
// libkolabxml throws errors on some deprecated timezone names
$utc_aliases
=
array
(
'UTC'
,
'GMT'
,
'+00:00'
,
'Z'
,
'Etc/GMT'
,
'Etc/UTC'
);
if
(
$tz
&&
in_array
(
$tz
->
getName
(),
$utc_aliases
))
{
$result
->
setUTC
(
true
);
}
else
if
(
$tz
!==
false
)
{
$tzid
=
$tz
->
getName
();
if
(
array_key_exists
(
$tzid
,
self
::
$timezone_map
))
$tzid
=
self
::
$timezone_map
[
$tzid
];
$result
->
setTimezone
(
$tzid
);
}
}
return
$result
;
}
/**
* Convert the given cDateTime into a PHP DateTime object
*
* @param object cDateTime The libkolabxml datetime object
* @return object DateTime PHP datetime instance
*/
public
static
function
php_datetime
(
$cdt
)
{
if
(!
is_object
(
$cdt
)
||
!
$cdt
->
isValid
())
return
null
;
$d
=
new
DateTime
;
$d
->
setTimezone
(
self
::
$timezone
);
try
{
if
(
$tzs
=
$cdt
->
timezone
())
{
$tz
=
new
DateTimeZone
(
$tzs
);
$d
->
setTimezone
(
$tz
);
}
else
if
(
$cdt
->
isUTC
())
{
$d
->
setTimezone
(
new
DateTimeZone
(
'UTC'
));
}
}
catch
(
Exception
$e
)
{
}
$d
->
setDate
(
$cdt
->
year
(),
$cdt
->
month
(),
$cdt
->
day
());
if
(
$cdt
->
isDateOnly
())
{
$d
->
_dateonly
=
true
;
$d
->
setTime
(
12
,
0
,
0
);
// set time to noon to avoid timezone troubles
}
else
{
$d
->
setTime
(
$cdt
->
hour
(),
$cdt
->
minute
(),
$cdt
->
second
());
}
return
$d
;
}
/**
* Convert a libkolabxml vector to a PHP array
*
* @param object vector Object
* @return array Indexed array containing vector elements
*/
public
static
function
vector2array
(
$vec
,
$max
=
PHP_INT_MAX
)
{
$arr
=
array
();
for
(
$i
=
0
;
$i
<
$vec
->
size
()
&&
$i
<
$max
;
$i
++)
$arr
[]
=
$vec
->
get
(
$i
);
return
$arr
;
}
/**
* Build a libkolabxml vector (string) from a PHP array
*
* @param array Array with vector elements
* @return object vectors
*/
public
static
function
array2vector
(
$arr
)
{
$vec
=
new
vectors
;
foreach
((
array
)
$arr
as
$val
)
{
if
(
strlen
(
$val
))
$vec
->
push
(
$val
);
}
return
$vec
;
}
/**
* Parse the X-Kolab-Type header from MIME messages and return the object type in short form
*
* @param string X-Kolab-Type header value
* @return string Kolab object type (contact,event,task,note,etc.)
*/
public
static
function
mime2object_type
(
$x_kolab_type
)
{
return
preg_replace
(
array
(
'/dictionary.[a-z.]+$/'
,
'/contact.distlist$/'
),
array
(
'dictionary'
,
'distribution-list'
),
substr
(
$x_kolab_type
,
strlen
(
self
::
KTYPE_PREFIX
))
);
}
/**
* Default constructor of all kolab_format_* objects
*/
public
function
__construct
(
$xmldata
=
null
,
$version
=
null
)
{
$this
->
obj
=
new
$this
->
objclass
;
$this
->
xmldata
=
$xmldata
;
if
(
$version
)
$this
->
version
=
$version
;
// use libkolab module if available
if
(
class_exists
(
'kolabobject'
))
$this
->
xmlobject
=
new
XMLObject
();
}
/**
* Check for format errors after calling kolabformat::write*()
*
* @return boolean True if there were errors, False if OK
*/
protected
function
format_errors
()
{
$ret
=
$log
=
false
;
switch
(
kolabformat
::
error
())
{
case
kolabformat
::
NoError
:
$ret
=
false
;
break
;
case
kolabformat
::
Warning
:
$ret
=
false
;
$uid
=
is_object
(
$this
->
obj
)
?
$this
->
obj
->
uid
()
:
$this
->
data
[
'uid'
];
$log
=
"Warning @ $uid"
;
break
;
default
:
$ret
=
true
;
$log
=
"Error"
;
}
if
(
$log
&&
!
isset
(
$this
->
formaterror
))
{
rcube
::
raise_error
(
array
(
'code'
=>
660
,
'type'
=>
'php'
,
'file'
=>
__FILE__
,
'line'
=>
__LINE__
,
'message'
=>
"kolabformat $log: "
.
kolabformat
::
errorMessage
(),
),
true
);
$this
->
formaterror
=
$ret
;
}
return
$ret
;
}
/**
* Save the last generated UID to the object properties.
* Should be called after kolabformat::writeXXXX();
*/
protected
function
update_uid
()
{
// get generated UID
if
(!
$this
->
data
[
'uid'
])
{
if
(
$this
->
xmlobject
)
{
$this
->
data
[
'uid'
]
=
$this
->
xmlobject
->
getSerializedUID
();
}
if
(
empty
(
$this
->
data
[
'uid'
]))
{
$this
->
data
[
'uid'
]
=
kolabformat
::
getSerializedUID
();
}
$this
->
obj
->
setUid
(
$this
->
data
[
'uid'
]);
}
}
/**
* Initialize libkolabxml object with cached xml data
*/
protected
function
init
()
{
if
(!
$this
->
loaded
)
{
if
(
$this
->
xmldata
)
{
$this
->
load
(
$this
->
xmldata
);
$this
->
xmldata
=
null
;
}
$this
->
loaded
=
true
;
}
}
/**
* Get constant value for libkolab's version parameter
*
* @param float Version value to convert
* @return int Constant value of either kolabobject::KolabV2 or kolabobject::KolabV3 or false if kolabobject module isn't available
*/
protected
function
libversion
(
$v
=
null
)
{
if
(
class_exists
(
'kolabobject'
))
{
$version
=
$v
?:
$this
->
version
;
if
(
$version
<=
'2.0'
)
return
kolabobject
::
KolabV2
;
else
return
kolabobject
::
KolabV3
;
}
return
false
;
}
/**
* Determine the correct libkolab(xml) wrapper function for the given call
* depending on the available PHP modules
*/
protected
function
libfunc
(
$func
)
{
if
(
is_array
(
$func
)
||
strpos
(
$func
,
'::'
))
return
$func
;
else
if
(
class_exists
(
'kolabobject'
))
return
array
(
$this
->
xmlobject
,
$func
);
else
return
'kolabformat::'
.
$func
;
}
/**
* Direct getter for object properties
*/
public
function
__get
(
$var
)
{
return
$this
->
data
[
$var
];
}
/**
* Load Kolab object data from the given XML block
*
* @param string XML data
* @return boolean True on success, False on failure
*/
public
function
load
(
$xml
)
{
$this
->
formaterror
=
null
;
$read_func
=
$this
->
libfunc
(
$this
->
read_func
);
if
(
is_array
(
$read_func
))
$r
=
call_user_func
(
$read_func
,
$xml
,
$this
->
libversion
());
else
$r
=
call_user_func
(
$read_func
,
$xml
,
false
);
if
(
is_resource
(
$r
))
$this
->
obj
=
new
$this
->
objclass
(
$r
);
else
if
(
is_a
(
$r
,
$this
->
objclass
))
$this
->
obj
=
$r
;
$this
->
loaded
=
!
$this
->
format_errors
();
}
/**
* Write object data to XML format
*
* @param float Format version to write
* @return string XML data
*/
public
function
write
(
$version
=
null
)
{
$this
->
formaterror
=
null
;
$this
->
init
();
$write_func
=
$this
->
libfunc
(
$this
->
write_func
);
if
(
is_array
(
$write_func
))
$this
->
xmldata
=
call_user_func
(
$write_func
,
$this
->
obj
,
$this
->
libversion
(
$version
),
self
::
PRODUCT_ID
);
else
$this
->
xmldata
=
call_user_func
(
$write_func
,
$this
->
obj
,
self
::
PRODUCT_ID
);
if
(!
$this
->
format_errors
())
$this
->
update_uid
();
else
$this
->
xmldata
=
null
;
return
$this
->
xmldata
;
}
/**
* Set properties to the kolabformat object
*
* @param array Object data as hash array
*/
public
function
set
(&
$object
)
{
$this
->
init
();
if
(!
empty
(
$object
[
'uid'
]))
$this
->
obj
->
setUid
(
$object
[
'uid'
]);
// set some automatic values if missing
if
(
method_exists
(
$this
->
obj
,
'setCreated'
))
{
// Always set created date to workaround libkolabxml (>1.1.4) bug
$created
=
$object
[
'created'
]
?:
new
DateTime
(
'now'
);
$created
->
setTimezone
(
new
DateTimeZone
(
'UTC'
));
// must be UTC
$this
->
obj
->
setCreated
(
self
::
get_datetime
(
$created
));
$object
[
'created'
]
=
$created
;
}
$object
[
'changed'
]
=
new
DateTime
(
'now'
,
new
DateTimeZone
(
'UTC'
));
$this
->
obj
->
setLastModified
(
self
::
get_datetime
(
$object
[
'changed'
]));
// Save custom properties of the given object
if
(
isset
(
$object
[
'x-custom'
])
&&
method_exists
(
$this
->
obj
,
'setCustomProperties'
))
{
$vcustom
=
new
vectorcs
;
foreach
((
array
)
$object
[
'x-custom'
]
as
$cp
)
{
if
(
is_array
(
$cp
))
$vcustom
->
push
(
new
CustomProperty
(
$cp
[
0
],
$cp
[
1
]));
}
$this
->
obj
->
setCustomProperties
(
$vcustom
);
}
// load custom properties from XML for caching (#2238) if method exists (#3125)
else
if
(
method_exists
(
$this
->
obj
,
'customProperties'
))
{
$object
[
'x-custom'
]
=
array
();
$vcustom
=
$this
->
obj
->
customProperties
();
for
(
$i
=
0
;
$i
<
$vcustom
->
size
();
$i
++)
{
$cp
=
$vcustom
->
get
(
$i
);
$object
[
'x-custom'
][]
=
array
(
$cp
->
identifier
,
$cp
->
value
);
}
}
}
/**
* Convert the Kolab object into a hash array data structure
*
* @param array Additional data for merge
*
* @return array Kolab object data as hash array
*/
public
function
to_array
(
$data
=
array
())
{
$this
->
init
();
// read object properties into local data object
$object
=
array
(
'uid'
=>
$this
->
obj
->
uid
(),
'changed'
=>
self
::
php_datetime
(
$this
->
obj
->
lastModified
()),
);
// not all container support the created property
if
(
method_exists
(
$this
->
obj
,
'created'
))
{
$object
[
'created'
]
=
self
::
php_datetime
(
$this
->
obj
->
created
());
}
// read custom properties
if
(
method_exists
(
$this
->
obj
,
'customProperties'
))
{
$vcustom
=
$this
->
obj
->
customProperties
();
for
(
$i
=
0
;
$i
<
$vcustom
->
size
();
$i
++)
{
$cp
=
$vcustom
->
get
(
$i
);
$object
[
'x-custom'
][]
=
array
(
$cp
->
identifier
,
$cp
->
value
);
}
}
// merge with additional data, e.g. attachments from the message
if
(
$data
)
{
foreach
(
$data
as
$idx
=>
$value
)
{
if
(
is_array
(
$value
))
{
$object
[
$idx
]
=
array_merge
((
array
)
$object
[
$idx
],
$value
);
}
else
{
$object
[
$idx
]
=
$value
;
}
}
}
return
$object
;
}
/**
* Object validation method to be implemented by derived classes
*/
abstract
public
function
is_valid
();
/**
* Callback for kolab_storage_cache to get object specific tags to cache
*
* @return array List of tags to save in cache
*/
public
function
get_tags
()
{
return
array
();
}
/**
* Callback for kolab_storage_cache to get words to index for fulltext search
*
* @return array List of words to save in cache
*/
public
function
get_words
()
{
return
array
();
}
/**
* Utility function to extract object attachment data
*
* @param array Hash array reference to append attachment data into
*/
public
function
get_attachments
(&
$object
,
$all
=
false
)
{
$this
->
init
();
// handle attachments
$vattach
=
$this
->
obj
->
attachments
();
for
(
$i
=
0
;
$i
<
$vattach
->
size
();
$i
++)
{
$attach
=
$vattach
->
get
(
$i
);
// skip cid: attachments which are mime message parts handled by kolab_storage_folder
if
(
substr
(
$attach
->
uri
(),
0
,
4
)
!=
'cid:'
&&
$attach
->
label
())
{
$name
=
$attach
->
label
();
$key
=
$name
.
(
isset
(
$object
[
'_attachments'
][
$name
])
?
'.'
.
$i
:
''
);
$content
=
$attach
->
data
();
$object
[
'_attachments'
][
$key
]
=
array
(
'id'
=>
'i:'
.
$i
,
'name'
=>
$name
,
'mimetype'
=>
$attach
->
mimetype
(),
'size'
=>
strlen
(
$content
),
'content'
=>
$content
,
);
}
else
if
(
$all
&&
substr
(
$attach
->
uri
(),
0
,
4
)
==
'cid:'
)
{
$key
=
$attach
->
uri
();
$object
[
'_attachments'
][
$key
]
=
array
(
'id'
=>
$key
,
'name'
=>
$attach
->
label
(),
'mimetype'
=>
$attach
->
mimetype
(),
);
}
else
if
(
in_array
(
substr
(
$attach
->
uri
(),
0
,
4
),
array
(
'http'
,
'imap'
)))
{
$object
[
'links'
][]
=
$attach
->
uri
();
}
}
}
/**
* Utility function to set attachment properties to the kolabformat object
*
* @param array Object data as hash array
* @param boolean True to always overwrite attachment information
*/
protected
function
set_attachments
(
$object
,
$write
=
true
)
{
// save attachments
$vattach
=
new
vectorattachment
;
foreach
((
array
)
$object
[
'_attachments'
]
as
$cid
=>
$attr
)
{
if
(
empty
(
$attr
))
continue
;
$attach
=
new
Attachment
;
$attach
->
setLabel
((
string
)
$attr
[
'name'
]);
$attach
->
setUri
(
'cid:'
.
$cid
,
$attr
[
'mimetype'
]
?:
'application/octet-stream'
);
if
(
$attach
->
isValid
())
{
$vattach
->
push
(
$attach
);
$write
=
true
;
}
else
{
rcube
::
raise_error
(
array
(
'code'
=>
660
,
'type'
=>
'php'
,
'file'
=>
__FILE__
,
'line'
=>
__LINE__
,
'message'
=>
"Invalid attributes for attachment $cid: "
.
var_export
(
$attr
,
true
),
),
true
);
}
}
foreach
((
array
)
$object
[
'links'
]
as
$link
)
{
$attach
=
new
Attachment
;
$attach
->
setUri
(
$link
,
'unknown'
);
$vattach
->
push
(
$attach
);
$write
=
true
;
}
if
(
$write
)
{
$this
->
obj
->
setAttachments
(
$vattach
);
}
}
/**
* Unified way of updating/deleting attachments of edited object
*
* @param array $object Kolab object data
* @param array $old Old version of Kolab object
*/
public
static
function
merge_attachments
(&
$object
,
$old
)
{
$object
[
'_attachments'
]
=
(
array
)
$old
[
'_attachments'
];
// delete existing attachment(s)
if
(!
empty
(
$object
[
'deleted_attachments'
]))
{
foreach
(
$object
[
'_attachments'
]
as
$idx
=>
$att
)
{
if
(
$object
[
'deleted_attachments'
]
===
true
||
in_array
(
$att
[
'id'
],
$object
[
'deleted_attachments'
]))
{
$object
[
'_attachments'
][
$idx
]
=
false
;
}
}
}
// in kolab_storage attachments are indexed by content-id
foreach
((
array
)
$object
[
'attachments'
]
as
$attachment
)
{
$key
=
null
;
// Roundcube ID has nothing to do with the storage ID, remove it
// for uploaded/new attachments
// FIXME: Roundcube uses 'data', kolab_format uses 'content'
if
(
$attachment
[
'content'
]
||
$attachment
[
'path'
]
||
$attachment
[
'data'
])
{
unset
(
$attachment
[
'id'
]);
}
if
(
$attachment
[
'id'
])
{
foreach
((
array
)
$object
[
'_attachments'
]
as
$cid
=>
$att
)
{
if
(
$att
&&
$attachment
[
'id'
]
==
$att
[
'id'
])
{
$key
=
$cid
;
}
}
}
else
{
// find attachment by name, so we can update it if exists
// and make sure there are no duplicates
foreach
((
array
)
$object
[
'_attachments'
]
as
$cid
=>
$att
)
{
if
(
$att
&&
$attachment
[
'name'
]
==
$att
[
'name'
])
{
$key
=
$cid
;
}
}
}
if
(
$key
&&
$attachment
[
'_deleted'
])
{
$object
[
'_attachments'
][
$key
]
=
false
;
}
// replace existing entry
else
if
(
$key
)
{
$object
[
'_attachments'
][
$key
]
=
$attachment
;
}
// append as new attachment
else
{
$object
[
'_attachments'
][]
=
$attachment
;
}
}
unset
(
$object
[
'attachments'
]);
unset
(
$object
[
'deleted_attachments'
]);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Mon, Apr 6, 1:16 AM (23 h, 24 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
bb/ce/5bd12caaa55a3c79ff7187554979
Default Alt Text
kolab_format.php (26 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline