Merge branch 'master' into chunked_upload

Conflicts:
	lib/connector/sabre/directory.php
This commit is contained in:
Bart Visscher 2012-07-27 11:40:51 +02:00
commit a7a5433108
638 changed files with 21925 additions and 5843 deletions

3
.gitignore vendored
View File

@ -34,6 +34,9 @@ RCS/*
# netbeans # netbeans
nbproject nbproject
# phpStorm
.idea
# geany # geany
*.geany *.geany

0
3rdparty/Sabre.includes.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Backend/Abstract.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Backend/PDO.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Calendar.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/CalendarObject.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/CalendarQueryParser.php vendored Normal file → Executable file
View File

28
3rdparty/Sabre/CalDAV/CalendarQueryValidator.php vendored Normal file → Executable file
View File

@ -294,6 +294,7 @@ class Sabre_CalDAV_CalendarQueryValidator {
// in the VALARM component code, so this is a hack, and an // in the VALARM component code, so this is a hack, and an
// expensive one too. // expensive one too.
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) { if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
// Fire up the iterator! // Fire up the iterator!
$it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID); $it = new Sabre_VObject_RecurrenceIterator($component->parent->parent, (string)$component->parent->UID);
while($it->valid()) { while($it->valid()) {
@ -304,14 +305,35 @@ class Sabre_CalDAV_CalendarQueryValidator {
// determine if we can 'give up' expanding events. // determine if we can 'give up' expanding events.
$firstAlarm = null; $firstAlarm = null;
foreach($expandedEvent->VALARM as $expandedAlarm) { foreach($expandedEvent->VALARM as $expandedAlarm) {
$effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime(); $effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
$firstAlarm = $effectiveTrigger;
}
if ($expandedAlarm->isInTimeRange($start, $end)) { if ($expandedAlarm->isInTimeRange($start, $end)) {
return true; return true;
} }
if ((string)$expandedAlarm->TRIGGER['VALUE'] === 'DATE-TIME') {
// This is an alarm with a non-relative trigger
// time, likely created by a buggy client. The
// implication is that every alarm in this
// recurring event trigger at the exact same
// time. It doesn't make sense to traverse
// further.
} else {
// We store the first alarm as a means to
// figure out when we can stop traversing.
if (!$firstAlarm || $effectiveTrigger < $firstAlarm) {
$firstAlarm = $effectiveTrigger;
}
}
}
if (is_null($firstAlarm)) {
// No alarm was found.
//
// Or technically: No alarm that will change for
// every instance of the recurrence was found,
// which means we can assume there was no match.
return false;
} }
if ($firstAlarm > $end) { if ($firstAlarm > $end) {
return false; return false;

0
3rdparty/Sabre/CalDAV/CalendarRootNode.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/ICSExportPlugin.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/ICalendar.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/ICalendarObject.php vendored Normal file → Executable file
View File

36
3rdparty/Sabre/CalDAV/Plugin.php vendored Normal file → Executable file
View File

@ -672,6 +672,42 @@ class Sabre_CalDAV_Plugin extends Sabre_DAV_ServerPlugin {
} }
if ($vobj->name !== 'VCALENDAR') {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support iCalendar objects.');
}
$foundType = null;
$foundUID = null;
foreach($vobj->getComponents() as $component) {
switch($component->name) {
case 'VTIMEZONE' :
continue 2;
case 'VEVENT' :
case 'VTODO' :
case 'VJOURNAL' :
if (is_null($foundType)) {
$foundType = $component->name;
if (!isset($component->UID)) {
throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' component must have an UID');
}
$foundUID = (string)$component->UID;
} else {
if ($foundType !== $component->name) {
throw new Sabre_DAV_Exception_BadRequest('A calendar object must only contain 1 component. We found a ' . $component->name . ' as well as a ' . $foundType);
}
if ($foundUID !== (string)$component->UID) {
throw new Sabre_DAV_Exception_BadRequest('Every ' . $component->name . ' in this object must have identical UIDs');
}
}
break;
default :
throw new Sabre_DAV_Exception_BadRequest('You are not allowed to create components of type: ' . $component->name . ' here');
}
}
if (!$foundType)
throw new Sabre_DAV_Exception_BadRequest('iCalendar object must contain at least 1 of VEVENT, VTODO or VJOURNAL');
} }
/** /**

0
3rdparty/Sabre/CalDAV/Principal/Collection.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Principal/ProxyRead.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Principal/ProxyWrite.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Principal/User.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Property/SupportedCalendarComponentSet.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Property/SupportedCalendarData.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Property/SupportedCollationSet.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Schedule/IMip.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Schedule/IOutbox.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Schedule/Outbox.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/Server.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CalDAV/UserCalendars.php vendored Normal file → Executable file
View File

2
3rdparty/Sabre/CalDAV/Version.php vendored Normal file → Executable file
View File

@ -14,7 +14,7 @@ class Sabre_CalDAV_Version {
/** /**
* Full version number * Full version number
*/ */
const VERSION = '1.6.2'; const VERSION = '1.6.3';
/** /**
* Stability : alpha, beta, stable * Stability : alpha, beta, stable

0
3rdparty/Sabre/CalDAV/includes.php vendored Normal file → Executable file
View File

2
3rdparty/Sabre/CardDAV/AddressBook.php vendored Normal file → Executable file
View File

@ -108,7 +108,9 @@ class Sabre_CardDAV_AddressBook extends Sabre_DAV_Collection implements Sabre_Ca
*/ */
public function createFile($name,$vcardData = null) { public function createFile($name,$vcardData = null) {
if (is_resource($vcardData)) {
$vcardData = stream_get_contents($vcardData); $vcardData = stream_get_contents($vcardData);
}
// Converting to UTF-8, if needed // Converting to UTF-8, if needed
$vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData); $vcardData = Sabre_DAV_StringUtil::ensureUTF8($vcardData);

16
3rdparty/Sabre/CardDAV/AddressBookQueryParser.php vendored Normal file → Executable file
View File

@ -88,12 +88,22 @@ class Sabre_CardDAV_AddressBookQueryParser {
if (is_nan($limit)) $limit = null; if (is_nan($limit)) $limit = null;
$filter = $this->xpath->query('/card:addressbook-query/card:filter'); $filter = $this->xpath->query('/card:addressbook-query/card:filter');
if ($filter->length !== 1) {
// According to the CardDAV spec there needs to be exactly 1 filter
// element. However, KDE 4.8.2 contains a bug that will encode 0 filter
// elements, so this is a workaround for that.
//
// See: https://bugs.kde.org/show_bug.cgi?id=300047
if ($filter->length === 0) {
$test = null;
$filter = null;
} elseif ($filter->length === 1) {
$filter = $filter->item(0);
$test = $this->xpath->evaluate('string(@test)', $filter);
} else {
throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed'); throw new Sabre_DAV_Exception_BadRequest('Only one filter element is allowed');
} }
$filter = $filter->item(0);
$test = $this->xpath->evaluate('string(@test)', $filter);
if (!$test) $test = self::TEST_ANYOF; if (!$test) $test = self::TEST_ANYOF;
if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) { if ($test !== self::TEST_ANYOF && $test !== self::TEST_ALLOF) {
throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"'); throw new Sabre_DAV_Exception_BadRequest('The test attribute must either hold "anyof" or "allof"');

0
3rdparty/Sabre/CardDAV/AddressBookRoot.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/Backend/Abstract.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/Backend/PDO.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/Card.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/IAddressBook.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/ICard.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/IDirectory.php vendored Normal file → Executable file
View File

79
3rdparty/Sabre/CardDAV/Plugin.php vendored Normal file → Executable file
View File

@ -52,6 +52,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$server->subscribeEvent('report', array($this,'report')); $server->subscribeEvent('report', array($this,'report'));
$server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel')); $server->subscribeEvent('onHTMLActionsPanel', array($this,'htmlActionsPanel'));
$server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction')); $server->subscribeEvent('onBrowserPostAction', array($this,'browserPostAction'));
$server->subscribeEvent('beforeWriteContent', array($this, 'beforeWriteContent'));
$server->subscribeEvent('beforeCreateFile', array($this, 'beforeCreateFile'));
/* Namespaces */ /* Namespaces */
$server->xmlNamespaces[self::NS_CARDDAV] = 'card'; $server->xmlNamespaces[self::NS_CARDDAV] = 'card';
@ -283,6 +285,81 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
} }
/**
* This method is triggered before a file gets updated with new content.
*
* This plugin uses this method to ensure that Card nodes receive valid
* vcard data.
*
* @param string $path
* @param Sabre_DAV_IFile $node
* @param resource $data
* @return void
*/
public function beforeWriteContent($path, Sabre_DAV_IFile $node, &$data) {
if (!$node instanceof Sabre_CardDAV_ICard)
return;
$this->validateVCard($data);
}
/**
* This method is triggered before a new file is created.
*
* This plugin uses this method to ensure that Card nodes receive valid
* vcard data.
*
* @param string $path
* @param resource $data
* @param Sabre_DAV_ICollection $parentNode
* @return void
*/
public function beforeCreateFile($path, &$data, Sabre_DAV_ICollection $parentNode) {
if (!$parentNode instanceof Sabre_CardDAV_IAddressBook)
return;
$this->validateVCard($data);
}
/**
* Checks if the submitted iCalendar data is in fact, valid.
*
* An exception is thrown if it's not.
*
* @param resource|string $data
* @return void
*/
protected function validateVCard(&$data) {
// If it's a stream, we convert it to a string first.
if (is_resource($data)) {
$data = stream_get_contents($data);
}
// Converting the data to unicode, if needed.
$data = Sabre_DAV_StringUtil::ensureUTF8($data);
try {
$vobj = Sabre_VObject_Reader::read($data);
} catch (Sabre_VObject_ParseException $e) {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This resource only supports valid vcard data. Parse error: ' . $e->getMessage());
}
if ($vobj->name !== 'VCARD') {
throw new Sabre_DAV_Exception_UnsupportedMediaType('This collection can only support vcard objects.');
}
}
/** /**
* This function handles the addressbook-query REPORT * This function handles the addressbook-query REPORT
* *
@ -362,6 +439,8 @@ class Sabre_CardDAV_Plugin extends Sabre_DAV_ServerPlugin {
$vcard = Sabre_VObject_Reader::read($vcardData); $vcard = Sabre_VObject_Reader::read($vcardData);
if (!$filters) return true;
foreach($filters as $filter) { foreach($filters as $filter) {
$isDefined = isset($vcard->{$filter['name']}); $isDefined = isset($vcard->{$filter['name']});

0
3rdparty/Sabre/CardDAV/Property/SupportedAddressData.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/CardDAV/UserAddressBooks.php vendored Normal file → Executable file
View File

2
3rdparty/Sabre/CardDAV/Version.php vendored Normal file → Executable file
View File

@ -16,7 +16,7 @@ class Sabre_CardDAV_Version {
/** /**
* Full version number * Full version number
*/ */
const VERSION = '1.6.1'; const VERSION = '1.6.3';
/** /**
* Stability : alpha, beta, stable * Stability : alpha, beta, stable

0
3rdparty/Sabre/CardDAV/includes.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Backend/AbstractBasic.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Backend/AbstractDigest.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Backend/Apache.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Backend/File.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Backend/PDO.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/IBackend.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Auth/Plugin.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Browser/GuessContentType.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Browser/MapGetToPropFind.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Browser/Plugin.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Browser/assets/favicon.ico vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/addressbook.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/calendar.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/card.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/collection.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/file.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/parent.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
3rdparty/Sabre/DAV/Browser/assets/icons/principal.png vendored Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

47
3rdparty/Sabre/DAV/Client.php vendored Normal file → Executable file
View File

@ -23,6 +23,28 @@ class Sabre_DAV_Client {
protected $password; protected $password;
protected $proxy; protected $proxy;
/**
* Basic authentication
*/
const AUTH_BASIC = 1;
/**
* Digest authentication
*/
const AUTH_DIGEST = 2;
/**
* The authentication type we're using.
*
* This is a bitmask of AUTH_BASIC and AUTH_DIGEST.
*
* If DIGEST is used, the client makes 1 extra request per request, to get
* the authentication tokens.
*
* @var int
*/
protected $authType;
/** /**
* Constructor * Constructor
* *
@ -46,16 +68,21 @@ class Sabre_DAV_Client {
'baseUri', 'baseUri',
'userName', 'userName',
'password', 'password',
'proxy' 'proxy',
); );
foreach($validSettings as $validSetting) { foreach($validSettings as $validSetting) {
if (isset($settings[$validSetting])) { if (isset($settings[$validSetting])) {
$this->$validSetting = $settings[$validSetting]; $this->$validSetting = $settings[$validSetting];
} }
} }
if (isset($settings['authType'])) {
$this->authType = $settings['authType'];
} else {
$this->authType = self::AUTH_BASIC | self::AUTH_DIGEST;
}
$this->propertyMap['{DAV:}resourcetype'] = 'Sabre_DAV_Property_ResourceType'; $this->propertyMap['{DAV:}resourcetype'] = 'Sabre_DAV_Property_ResourceType';
} }
@ -250,14 +277,9 @@ class Sabre_DAV_Client {
// Automatically follow redirects // Automatically follow redirects
CURLOPT_FOLLOWLOCATION => true, CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5, CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => true,
//CURLOPT_SSL_VERIFYPEER => false,
); );
switch ($method) { switch ($method) {
case 'PUT':
$curlSettings[CURLOPT_PUT] = true;
break;
case 'HEAD' : case 'HEAD' :
// do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD // do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD
@ -288,8 +310,15 @@ class Sabre_DAV_Client {
$curlSettings[CURLOPT_PROXY] = $this->proxy; $curlSettings[CURLOPT_PROXY] = $this->proxy;
} }
if ($this->userName) { if ($this->userName && $this->authType) {
$curlSettings[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST; $curlType = 0;
if ($this->authType & self::AUTH_BASIC) {
$curlType |= CURLAUTH_BASIC;
}
if ($this->authType & self::AUTH_DIGEST) {
$curlType |= CURLAUTH_DIGEST;
}
$curlSettings[CURLOPT_HTTPAUTH] = $curlType;
$curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password; $curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
} }

0
3rdparty/Sabre/DAV/Collection.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Directory.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/BadRequest.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/Conflict.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/ConflictingLock.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/FileNotFound.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/Forbidden.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/InsufficientStorage.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/InvalidResourceType.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/LockTokenMatchesRequestUri.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/Locked.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/MethodNotAllowed.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/NotAuthenticated.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/NotFound.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/NotImplemented.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/PaymentRequired.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/PreconditionFailed.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/ReportNotImplemented.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/RequestedRangeNotSatisfiable.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Exception/UnsupportedMediaType.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FS/Directory.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FS/File.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FS/Node.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FSExt/Directory.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FSExt/File.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/FSExt/Node.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/File.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/ICollection.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/IExtendedCollection.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/IFile.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/INode.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/IProperties.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/IQuota.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/Backend/Abstract.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/Backend/FS.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/Backend/File.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/Backend/PDO.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/LockInfo.php vendored Normal file → Executable file
View File

0
3rdparty/Sabre/DAV/Locks/Plugin.php vendored Normal file → Executable file
View File

Some files were not shown because too many files have changed in this diff Show More