diff --git a/apps/calendar/ajax/editevent.php b/apps/calendar/ajax/editevent.php
index 46feb068499e0e96897cc95005dc75f1e01bf5e5..e3c84520481cc603d75980ca762f99c40392d022 100644
--- a/apps/calendar/ajax/editevent.php
+++ b/apps/calendar/ajax/editevent.php
@@ -34,7 +34,7 @@ if($errarr){
 		OC_JSON::error();
 		exit;
 	}
-	$vcalendar = OC_Calendar_Object::parse($data['calendardata']);
+	$vcalendar = OC_VObject::parse($data['calendardata']);
 
 	$last_modified = $vcalendar->VEVENT->__get('LAST-MODIFIED');
 	if($last_modified && $_POST['lastmodified'] != $last_modified->getDateTime()->format('U')){
diff --git a/apps/calendar/ajax/editeventform.php b/apps/calendar/ajax/editeventform.php
index 63c729340791e1ec6ea733a512ef8b57a7ad8502..c91f136e89875098088f2ad69b38508a8cc054d2 100644
--- a/apps/calendar/ajax/editeventform.php
+++ b/apps/calendar/ajax/editeventform.php
@@ -26,7 +26,7 @@ if($calendar['userid'] != OC_User::getUser()){
 		echo $l10n->t('Wrong calendar');
 		exit;
 }
-$object = OC_Calendar_Object::parse($data['calendardata']);
+$object = OC_VObject::parse($data['calendardata']);
 $vevent = $object->VEVENT;
 $dtstart = $vevent->DTSTART;
 $dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
@@ -49,20 +49,16 @@ switch($dtstart->getDateType()) {
 		break;
 }
 
-$summary = isset($vevent->SUMMARY) ? $vevent->SUMMARY->value : '';
-$location = isset($vevent->LOCATION) ? $vevent->LOCATION->value : '';
-$categories = array();
-if (isset($vevent->CATEGORIES)){
-       $categories = explode(',', $vevent->CATEGORIES->value);
-       $categories = array_map('trim', $categories);
-}
+$summary = $vevent->getAsString('SUMMARY');
+$location = $vevent->getAsString('LOCATION');
+$categories = $vevent->getAsArray('CATEGORIES');
+$repeat = $vevent->getAsString('CATEGORY');
+$description = $vevent->getAsString('DESCRIPTION');
 foreach($categories as $category){
 	if (!in_array($category, $category_options)){
 		array_unshift($category_options, $category);
 	}
 }
-$repeat = isset($vevent->CATEGORY) ? $vevent->CATEGORY->value : '';
-$description = isset($vevent->DESCRIPTION) ? $vevent->DESCRIPTION->value : '';
 $last_modified = $vevent->__get('LAST-MODIFIED');
 if ($last_modified){
 	$lastmodified = $last_modified->getDateTime()->format('U');
diff --git a/apps/calendar/ajax/events.php b/apps/calendar/ajax/events.php
index 1ef6bd30594b86900955ff98da6420c338a16963..1430432b8a3fc69909dc37f89183461af0556b46 100644
--- a/apps/calendar/ajax/events.php
+++ b/apps/calendar/ajax/events.php
@@ -33,7 +33,7 @@ $events = OC_Calendar_Object::allInPeriod($_GET['calendar_id'], $start, $end);
 $user_timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 $return = array();
 foreach($events as $event){
-	$object = OC_Calendar_Object::parse($event['calendardata']);
+	$object = OC_VObject::parse($event['calendardata']);
 	$vevent = $object->VEVENT;
 	$dtstart = $vevent->DTSTART;
 	$dtend = OC_Calendar_Object::getDTEndFromVEvent($vevent);
diff --git a/apps/calendar/ajax/moveevent.php b/apps/calendar/ajax/moveevent.php
index 6b315a3921345e509c9b4e54a0827e2fc58f8e40..51fafdfeb97b95f9b79da860e1a548c31b46e50f 100644
--- a/apps/calendar/ajax/moveevent.php
+++ b/apps/calendar/ajax/moveevent.php
@@ -22,7 +22,7 @@ $delta = new DateInterval('P0D');
 $delta->d = $_POST['dayDelta'];
 $delta->i = $_POST['minuteDelta'];
 
-$vcalendar = OC_Calendar_Object::parse($data['calendardata']);
+$vcalendar = OC_VObject::parse($data['calendardata']);
 $vevent = $vcalendar->VEVENT;
 
 $last_modified = $vevent->__get('LAST-MODIFIED');
@@ -46,14 +46,8 @@ $dtstart->setDateTime($dtstart->getDateTime()->add($delta), $start_type);
 $dtend->setDateTime($dtend->getDateTime()->add($delta), $end_type);
 unset($vevent->DURATION);
 
-$now = new DateTime();
-$last_modified = new Sabre_VObject_Element_DateTime('LAST-MODIFIED');
-$last_modified->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
-$vevent->__set('LAST-MODIFIED', $last_modified);
-
-$dtstamp = new Sabre_VObject_Element_DateTime('DTSTAMP');
-$dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
-$vevent->DTSTAMP = $dtstamp;
+$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
+$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
 
 $result = OC_Calendar_Object::edit($id, $vcalendar->serialize());
 OC_JSON::success(array('lastmodified'=>(int)$now->format('U')));
diff --git a/apps/calendar/lib/object.php b/apps/calendar/lib/object.php
index b0164690429af90b567cb21291b6ed8fe4b01780..1e834241f630b62eb96943f320886ea7f0a2fc31 100644
--- a/apps/calendar/lib/object.php
+++ b/apps/calendar/lib/object.php
@@ -92,7 +92,7 @@ class OC_Calendar_Object{
 	 * @return insertid
 	 */
 	public static function add($id,$data){
-		$object = self::parse($data);
+		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
 		if(is_null($uid)){
@@ -119,7 +119,7 @@ class OC_Calendar_Object{
 	 * @return insertid
 	 */
 	public static function addFromDAVData($id,$uri,$data){
-		$object = self::parse($data);
+		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
 		$stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*calendar_objects (calendarid,objecttype,startdate,enddate,repeating,summary,calendardata,uri,lastmodified) VALUES(?,?,?,?,?,?,?,?,?)' );
@@ -139,7 +139,7 @@ class OC_Calendar_Object{
 	public static function edit($id, $data){
 		$oldobject = self::find($id);
 
-		$object = self::parse($data);
+		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
 		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
@@ -160,7 +160,7 @@ class OC_Calendar_Object{
 	public static function editFromDAVData($cid,$uri,$data){
 		$oldobject = self::findWhereDAVDataIs($cid,$uri);
 
-		$object = self::parse($data);
+		$object = OC_VObject::parse($data);
 		list($type,$startdate,$enddate,$summary,$repeating,$uid) = self::extractData($object);
 
 		$stmt = OC_DB::prepare( 'UPDATE *PREFIX*calendar_objects SET objecttype=?,startdate=?,enddate=?,repeating=?,summary=?,calendardata=?, lastmodified = ? WHERE id = ?' );
@@ -228,7 +228,7 @@ class OC_Calendar_Object{
 		// Child to use
 		$children = 0;
 		$use = null;
-		foreach($object->children as &$property){
+		foreach($object->children as $property){
 			if($property->name == 'VEVENT'){
 				$children++;
 				$thisone = true;
@@ -259,12 +259,12 @@ class OC_Calendar_Object{
 				//    one VTODO per object)
 				break;
 			}
-		} unset($property);
+		}
 
 		// find the data
 		if(!is_null($use)){
 			$return[0] = $use->name;
-			foreach($use->children as &$property){
+			foreach($use->children as $property){
 				if($property->name == 'DTSTART'){
 					$return[1] = self::getUTCforMDB($property->getDateTime());
 				}
@@ -280,7 +280,7 @@ class OC_Calendar_Object{
 				elseif($property->name == 'UID'){
 					$return[5] = $property->value;
 				}
-			} unset($property);
+			}
 		}
 
 		// More than one child means reoccuring!
@@ -302,21 +302,6 @@ class OC_Calendar_Object{
 		return date('Y-m-d H:i', $datetime->format('U') - $datetime->getOffset());
 	}
 
-	/**
-	 * @brief Parses the VObject
-	 * @param string VObject as string
-	 * @returns Sabre_VObject or null
-	 */
-	public static function parse($data){
-		try {
-			Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime';
-			$calendar = Sabre_VObject_Reader::read($data);
-			return $calendar;
-		} catch (Exception $e) {
-			return null;
-		}
-	}
-
 	public static function getDTEndFromVEvent($vevent)
 	{
 		if ($vevent->DTEND) {
@@ -458,22 +443,16 @@ class OC_Calendar_Object{
 
 	public static function createVCalendarFromRequest($request)
 	{
-		$vcalendar = new Sabre_VObject_Component('VCALENDAR');
+		$vcalendar = new OC_VObject('VCALENDAR');
 		$vcalendar->add('PRODID', 'ownCloud Calendar');
 		$vcalendar->add('VERSION', '2.0');
 
-		$now = new DateTime();
-
-		$vevent = new Sabre_VObject_Component('VEVENT');
+		$vevent = new OC_VObject('VEVENT');
 		$vcalendar->add($vevent);
 
-		$created = new Sabre_VObject_Element_DateTime('CREATED');
-		$created->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
-		$vevent->add($created);
-
-		$uid = self::createUID();
-		$vevent->add('UID',$uid);
+		$vevent->setDateTime('CREATED', 'now', Sabre_VObject_Element_DateTime::UTC);
 
+		$vevent->setUID();
 		return self::updateVCalendarFromRequest($request, $vcalendar);
 	}
 
@@ -509,43 +488,31 @@ class OC_Calendar_Object{
 		}*/
 		$repeat = "false";
 
-		$now = new DateTime();
-		$vevent = $vcalendar->VEVENT[0];
-
-		$last_modified = new Sabre_VObject_Element_DateTime('LAST-MODIFIED');
-		$last_modified->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
-		$vevent->__set('LAST-MODIFIED', $last_modified);
-
-		$dtstamp = new Sabre_VObject_Element_DateTime('DTSTAMP');
-		$dtstamp->setDateTime($now, Sabre_VObject_Element_DateTime::UTC);
-		$vevent->DTSTAMP = $dtstamp;
+		$vevent = $vcalendar->VEVENT;
 
-		$vevent->SUMMARY = $title;
+		$vevent->setDateTime('LAST-MODIFIED', 'now', Sabre_VObject_Element_DateTime::UTC);
+		$vevent->setDateTime('DTSTAMP', 'now', Sabre_VObject_Element_DateTime::UTC);
+		$vevent->setString('SUMMARY', $title);
 
 		$dtstart = new Sabre_VObject_Element_DateTime('DTSTART');
 		$dtend = new Sabre_VObject_Element_DateTime('DTEND');
 		if($allday){
 			$start = new DateTime($from);
 			$end = new DateTime($to.' +1 day');
-			$dtstart->setDateTime($start, Sabre_VObject_Element_DateTime::DATE);
-			$dtend->setDateTime($end, Sabre_VObject_Element_DateTime::DATE);
+			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::DATE);
+			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::DATE);
 		}else{
 			$timezone = OC_Preferences::getValue(OC_USER::getUser(), 'calendar', 'timezone', date_default_timezone_get());
 			$timezone = new DateTimeZone($timezone);
 			$start = new DateTime($from.' '.$fromtime, $timezone);
 			$end = new DateTime($to.' '.$totime, $timezone);
-			$dtstart->setDateTime($start, Sabre_VObject_Element_DateTime::LOCALTZ);
-			$dtend->setDateTime($end, Sabre_VObject_Element_DateTime::LOCALTZ);
+			$vevent->setDateTime('DTSTART', $start, Sabre_VObject_Element_DateTime::LOCALTZ);
+			$vevent->setDateTime('DTEND', $end, Sabre_VObject_Element_DateTime::LOCALTZ);
 		}
-		$vevent->DTSTART = $dtstart;
-		$vevent->DTEND = $dtend;
 		unset($vevent->DURATION);
 
-		if($location != ""){
-			$vevent->LOCATION = $location;
-		}else{
-			unset($vevent->LOCATION);
-		}
+
+		$vevent->setString('LOCATION', $location);
 
 		if($description != ""){
 			$vevent->DESCRIPTION = $description;
diff --git a/apps/contacts/ajax/addcard.php b/apps/contacts/ajax/addcard.php
index dd5b90651f56321b93c96d65de91a9eb59890527..8d192641dbdf1c5ec6e761b2948746dce775901e 100644
--- a/apps/contacts/ajax/addcard.php
+++ b/apps/contacts/ajax/addcard.php
@@ -40,9 +40,9 @@ $fn = $_POST['fn'];
 $values = $_POST['value'];
 $parameters = $_POST['parameters'];
 
-$vcard = new Sabre_VObject_Component('VCARD');
-$vcard->add(new Sabre_VObject_Property('FN',$fn));
-$vcard->add(new Sabre_VObject_Property('UID',OC_Contacts_VCard::createUID()));
+$vcard = new OC_VObject('VCARD');
+$vcard->setUID();
+$vcard->setString('FN',$fn);
 
 // Data to add ...
 $add = array('TEL', 'EMAIL', 'ORG');
@@ -64,7 +64,7 @@ foreach( $add as $propname){
 	else{
 		$prop_parameters = array();
 	}
-	OC_Contacts_VCard::addVCardProperty($vcard, $propname, $value, $prop_parameters);
+	$vcard->addProperty($propname, $value, $prop_parameters);
 }
 $id = OC_Contacts_VCard::add($aid,$vcard->serialize());
 
diff --git a/apps/contacts/ajax/addproperty.php b/apps/contacts/ajax/addproperty.php
index 101cfabbe84c8ef7e50da66d92ef0a77c9ed20fd..e59a91e4a58fdbf1c68170986cc3edb920338e64 100644
--- a/apps/contacts/ajax/addproperty.php
+++ b/apps/contacts/ajax/addproperty.php
@@ -42,7 +42,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$vcard = OC_Contacts_VCard::parse($card['carddata']);
+$vcard = OC_VObject::parse($card['carddata']);
 // Check if the card is valid
 if(is_null($vcard)){
 	OC_JSON::error(array('data' => array( 'message' => $l10n->t('vCard could not be read.'))));
@@ -53,7 +53,7 @@ $name = $_POST['name'];
 $value = $_POST['value'];
 $parameters = isset($_POST['parameteres'])?$_POST['parameters']:array();
 
-$property = OC_Contacts_VCard::addVCardProperty($vcard, $name, $value, $parameters);
+$property = $vcard->addProperty($name, $value, $parameters);
 
 $line = count($vcard->children) - 1;
 $checksum = md5($property->serialize());
diff --git a/apps/contacts/ajax/deleteproperty.php b/apps/contacts/ajax/deleteproperty.php
index 0a3a3c293a0439e5b4a54ba2f9f32bd2d9718bc2..be352cea616b236bad4f4449c99c848119aa8a54 100644
--- a/apps/contacts/ajax/deleteproperty.php
+++ b/apps/contacts/ajax/deleteproperty.php
@@ -45,7 +45,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$vcard = OC_Contacts_VCard::parse($card['carddata']);
+$vcard = OC_VObject::parse($card['carddata']);
 // Check if the card is valid
 if(is_null($vcard)){
 	OC_JSON::error(array('data' => array( 'message' => $l10n->t('vCard could not be read.'))));
diff --git a/apps/contacts/ajax/getdetails.php b/apps/contacts/ajax/getdetails.php
index 260fb53a6862b5562640fd0040862e9fd90a1fcb..eb1f20ee75e4d5f7e8fa884cfbfdf4d22807b8ee 100644
--- a/apps/contacts/ajax/getdetails.php
+++ b/apps/contacts/ajax/getdetails.php
@@ -44,7 +44,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$vcard = OC_Contacts_VCard::parse($card['carddata']);
+$vcard = OC_VObject::parse($card['carddata']);
 // Check if the card is valid
 if(is_null($vcard)){
 	OC_JSON::error(array('data' => array( 'message' => $l10n->t('vCard could not be read.'))));
diff --git a/apps/contacts/ajax/setproperty.php b/apps/contacts/ajax/setproperty.php
index 22f228cbf437e81a8c78434b0597ef05dd672905..2edfa5b452f1964c102690dcde6ca7e74a0f9550 100644
--- a/apps/contacts/ajax/setproperty.php
+++ b/apps/contacts/ajax/setproperty.php
@@ -43,7 +43,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$vcard = OC_Contacts_VCard::parse($card['carddata']);
+$vcard = OC_VObject::parse($card['carddata']);
 // Check if the card is valid
 if(is_null($vcard)){
 	OC_JSON::error(array('data' => array( 'message' => $l10n->t('vCard could not be read.'))));
@@ -64,7 +64,7 @@ if(is_null($line)){
 // Set the value
 $value = $_POST['value'];
 if(is_array($value)){
-	$value = OC_Contacts_VCard::escapeSemicolons($value);
+	$value = OC_VObject::escapeSemicolons($value);
 }
 $vcard->children[$line]->setValue($value);
 
diff --git a/apps/contacts/ajax/showsetproperty.php b/apps/contacts/ajax/showsetproperty.php
index 2ec4b89b8247b28e70877b7ef3ec7a10422a0e91..1cf6541780902dbd9e599084ea7d2d90c3438ec1 100644
--- a/apps/contacts/ajax/showsetproperty.php
+++ b/apps/contacts/ajax/showsetproperty.php
@@ -43,7 +43,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$vcard = OC_Contacts_VCard::parse($card['carddata']);
+$vcard = OC_VObject::parse($card['carddata']);
 // Check if the card is valid
 if(is_null($vcard)){
 	OC_JSON::error(array('data' => array( 'message' => $l10n->t('vCard could not be read.'))));
diff --git a/apps/contacts/index.php b/apps/contacts/index.php
index 29d41d3c4c45b948217ebf3a543d1b8bc1327c34..744b69023312d211206c04448b8d37ee12bd7ad4 100644
--- a/apps/contacts/index.php
+++ b/apps/contacts/index.php
@@ -71,7 +71,7 @@ $details = array();
 if( !is_null($id) || count($contacts)){
 	if(is_null($id)) $id = $contacts[0]['id'];
 	$contact = OC_Contacts_VCard::find($id);
-	$vcard = OC_Contacts_VCard::parse($contact['carddata']);
+	$vcard = OC_VObject::parse($contact['carddata']);
 	$details = OC_Contacts_VCard::structureContact($vcard);
 }
 
diff --git a/apps/contacts/lib/vcard.php b/apps/contacts/lib/vcard.php
index 4865fae7642538171f90cbcb3debbffeeb2f7da6..8836431ddbb1ec116f00d8c0a9bad3c80276b935 100644
--- a/apps/contacts/lib/vcard.php
+++ b/apps/contacts/lib/vcard.php
@@ -91,31 +91,21 @@ class OC_Contacts_VCard{
 	 */
 	public static function add($id,$data){
 		$fn = null;
-		$uri = null;
 
-		$card = self::parse($data);
+		$card = OC_VObject::parse($data);
 		if(!is_null($card)){
-			// VCARD must have a version
-			$hasversion = false;
-			foreach($card->children as $property){
-				if($property->name == 'FN'){
-					$fn = $property->value;
-				}
-				elseif($property->name == 'VERSION'){
-					$hasversion = true;
-				}
-				elseif(is_null($uri) && $property->name == 'UID' ){
-					$uri = $property->value.'.vcf';
-				}
-			}
-			if(is_null($uri)){
-				$uid = self::createUID();
-				$uri = $uid.'.vcf';
-				$card->add(new Sabre_VObject_Property('UID',$uid));
+			$fn = $card->getAsString('FN');
+			$uid = $card->getAsString('UID');
+			if(is_null($uid)){
+				$card->setUID();
+				$uid = $card->getAsString('UID');
 				$data = $card->serialize();
 			};
+			$uri = $uid.'.vcf';
+			// VCARD must have a version
+			$version = $card->getAsString('VERSION');
 			// Add version if needed
-			if(!$hasversion){
+			if(is_null($version)){
 				$card->add(new Sabre_VObject_Property('VERSION','3.0'));
 				$data = $card->serialize();
 			}
@@ -143,7 +133,7 @@ class OC_Contacts_VCard{
 	 */
 	public static function addFromDAVData($id,$uri,$data){
 		$fn = null;
-		$card = self::parse($data);
+		$card = OC_VObject::parse($data);
 		if(!is_null($card)){
 			foreach($card->children as $property){
 				if($property->name == 'FN'){
@@ -170,7 +160,7 @@ class OC_Contacts_VCard{
 		$oldcard = self::find($id);
 		$fn = null;
 
-		$card = self::parse($data);
+		$card = OC_VObject::parse($data);
 		if(!is_null($card)){
 			foreach($card->children as $property){
 				if($property->name == 'FN'){
@@ -198,7 +188,7 @@ class OC_Contacts_VCard{
 		$oldcard = self::findWhereDAVDataIs($aid,$uri);
 
 		$fn = null;
-		$card = self::parse($data);
+		$card = OC_VObject::parse($data);
 		if(!is_null($card)){
 			foreach($card->children as $property){
 				if($property->name == 'FN'){
@@ -248,67 +238,6 @@ class OC_Contacts_VCard{
 		return true;
 	}
 
-	/**
-	 * @brief Escapes semicolons
-	 * @param string $value
-	 * @return string
-	 */
-	public static function escapeSemicolons($value){
-		foreach($value as &$i ){
-			$i = implode("\\\\;", explode(';', $i));
-		}
-		return implode(';',$value);
-	}
-
-	/**
-	 * @brief Creates an array out of a multivalue property
-	 * @param string $value
-	 * @return array
-	 */
-	public static function unescapeSemicolons($value){
-		$array = explode(';',$value);
-		for($i=0;$i<count($array);$i++){
-			if(substr($array[$i],-2,2)=="\\\\"){
-				if(isset($array[$i+1])){
-					$array[$i] = substr($array[$i],0,count($array[$i])-2).';'.$array[$i+1];
-					unset($array[$i+1]);
-				}
-				else{
-					$array[$i] = substr($array[$i],0,count($array[$i])-2).';';
-				}
-				$i = $i - 1;
-			}
-		}
-		return $array;
-	}
-
-	/**
-	 * @brief Add property to vcard object
-	 * @param object $vcard
-	 * @param object $name of property
-	 * @param object $value of property
-	 * @param object $paramerters of property
-	 */
-	public static function addVCardProperty($vcard, $name, $value, $parameters=array()){
-		if(is_array($value)){
-			$value = OC_Contacts_VCard::escapeSemicolons($value);
-		}
-		$property = new Sabre_VObject_Property( $name, $value );
-		$parameternames = array_keys($parameters);
-		foreach($parameternames as $i){
-			$values = $parameters[$i];
-			if (!is_array($values)){
-				$values = array($values);
-			}
-			foreach($values as $value){
-				$property->add($i, $value);
-			}
-		}
-
-		$vcard->add($property);
-		return $property;
-	}
-
 	/**
 	 * @brief Data structure of vCard
 	 * @param object $property
@@ -345,7 +274,7 @@ class OC_Contacts_VCard{
 		$value = $property->value;
 		$value = htmlspecialchars($value);
 		if($property->name == 'ADR' || $property->name == 'N'){
-			$value = self::unescapeSemicolons($value);
+			$value = OC_VObject::unescapeSemicolons($value);
 		}
 		$temp = array(
 			'name' => $property->name,
@@ -373,21 +302,6 @@ class OC_Contacts_VCard{
 		return $temp;
 	}
 
-	/**
-	 * @brief Parses a vcard file
-	 * @param string vCard
-	 * @return Sabre_VObject or null
-	 *
-	 * Will retun the vobject if sabre DAV is able to parse the file.
-	 */
-	public static function parse($data){
-		try {
-			$card = Sabre_VObject_Reader::read($data);
-			return $card;
-		} catch (Exception $e) {
-			return null;
-		}
-	}
 	public static function getTypesOfProperty($l, $prop){
 		switch($prop){
 		case 'ADR':
diff --git a/apps/contacts/photo.php b/apps/contacts/photo.php
index 5178fe7a078d021e5f790fe0b263f945de11c028..60dd81140bf13a3e414eda461cecffefd5af1b2f 100644
--- a/apps/contacts/photo.php
+++ b/apps/contacts/photo.php
@@ -41,7 +41,7 @@ if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
 	exit();
 }
 
-$content = OC_Contacts_VCard::parse($card['carddata']);
+$content = OC_VObject::parse($card['carddata']);
 
 // invalid vcard
 if( is_null($content)){
diff --git a/lib/vobject.php b/lib/vobject.php
new file mode 100644
index 0000000000000000000000000000000000000000..5a76cfd2d43031ff7142fa2f141166e1133454a9
--- /dev/null
+++ b/lib/vobject.php
@@ -0,0 +1,201 @@
+<?php
+/**
+ * ownCloud
+ *
+ * @author Bart Visscher
+ * @copyright 2011 Bart Visscher bartv@thisnet.nl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/**
+ * This class provides a streamlined interface to the Sabre VObject classes
+ */
+class OC_VObject{
+	/** @var Sabre_VObject_Component */
+	protected $vobject;
+
+	/**
+	 * @returns Sabre_VObject_Component
+	 */
+	public function getVObject(){
+		return $this->vobject;
+	}
+
+	/**
+	 * @brief Parses the VObject
+	 * @param string VObject as string
+	 * @returns Sabre_VObject or null
+	 */
+	public static function parse($data){
+		try {
+			Sabre_VObject_Reader::$elementMap['LAST-MODIFIED'] = 'Sabre_VObject_Element_DateTime';
+			$vobject = Sabre_VObject_Reader::read($data);
+			if ($vobject instanceof Sabre_VObject_Component){
+				$vobject = new OC_VObject($vobject);
+			}
+			return $vobject;
+		} catch (Exception $e) {
+			return null;
+		}
+	}
+
+	/**
+	 * @brief Escapes semicolons
+	 * @param string $value
+	 * @return string
+	 */
+	public static function escapeSemicolons($value){
+		foreach($value as &$i ){
+			$i = implode("\\\\;", explode(';', $i));
+		}
+		return implode(';',$value);
+	}
+
+	/**
+	 * @brief Creates an array out of a multivalue property
+	 * @param string $value
+	 * @return array
+	 */
+	public static function unescapeSemicolons($value){
+		$array = explode(';',$value);
+		for($i=0;$i<count($array);$i++){
+			if(substr($array[$i],-2,2)=="\\\\"){
+				if(isset($array[$i+1])){
+					$array[$i] = substr($array[$i],0,count($array[$i])-2).';'.$array[$i+1];
+					unset($array[$i+1]);
+				}
+				else{
+					$array[$i] = substr($array[$i],0,count($array[$i])-2).';';
+				}
+				$i = $i - 1;
+			}
+		}
+		return $array;
+	}
+
+	/**
+	 * Constuctor
+	 * @param Sabre_VObject_Component or string
+	 */
+	public function __construct($vobject_or_name){
+		if (is_object($vobject_or_name)){
+			$this->vobject = $vobject_or_name;
+		} else {
+			$this->vobject = new Sabre_VObject_Component($vobject_or_name);
+		}
+	}
+
+	public function add($item, $itemValue = null){
+		if ($item instanceof OC_VObject){
+			$item = $item->getVObject();
+		}
+		$this->vobject->add($item, $itemValue);
+	}
+
+	/**
+	 * @brief Add property to vobject
+	 * @param object $name of property
+	 * @param object $value of property
+	 * @param object $parameters of property
+	 * @returns Sabre_VObject_Property newly created
+	 */
+	public function addProperty($name, $value, $parameters=array()){
+		if(is_array($value)){
+			$value = OC_VObject::escapeSemicolons($value);
+		}
+		$property = new Sabre_VObject_Property( $name, $value );
+		foreach($parameters as $name => $value){
+			$property->parameters[] = new Sabre_VObject_Parameter($name, $value);
+		}
+
+		$this->vobject->add($property);
+		return $property;
+	}
+
+	public function setUID(){
+		$uid = substr(md5(rand().time()),0,10);
+		$this->vobject->add('UID',$uid);
+	}
+
+	public function setString($name, $string){
+		if ($string != ''){
+			$this->vobject->__set($name, $string);
+		}else{
+			$this->vobject->__unset($name);
+		}
+	}
+
+	/**
+	 * Sets or unsets the Date and Time for a property.
+	 * When $datetime is set to 'now', use the current time
+	 * When $datetime is null, unset the property
+	 *
+	 * @param string property name
+	 * @param DateTime $datetime
+	 * @param int $dateType
+	 * @return void
+	 */
+	public function setDateTime($name, $datetime, $dateType=Sabre_VObject_Element_DateTime::LOCALTZ){
+		if ($datetime == 'now'){
+			$datetime = new DateTime();
+		}
+		if ($datetime instanceof DateTime){
+			$datetime_element = new Sabre_VObject_Element_DateTime($name);
+			$datetime_element->setDateTime($datetime, $dateType);
+			$this->vobject->__set($name, $datetime_element);
+		}else{
+			$this->vobject->__unset($name);
+		}
+	}
+
+	public function getAsString($name){
+		return $this->vobject->__isset($name) ?
+			$this->vobject->__get($name)->value :
+			'';
+	}
+
+	public function getAsArray($name){
+		$values = array();
+		if ($this->vobject->__isset($name)){
+			$values = explode(',', $this->getAsString($name));
+			$values = array_map('trim', $values);
+		}
+		return $values;
+	}
+
+	public function &__get($name){
+		if ($name == 'children'){
+			return $this->vobject->children;
+		}
+		$return = $this->vobject->__get($name);
+		if ($return instanceof Sabre_VObject_Component){
+			$return = new OC_VObject($return);
+		}
+		return $return;
+	}
+
+	public function __set($name, $value){
+		return $this->vobject->__set($name, $value);
+	}
+
+	public function __unset($name){
+		return $this->vobject->__unset($name);
+	}
+
+	public function __call($function,$arguments){
+		return call_user_func_array(array($this->vobject, $function), $arguments);
+	}
+}