22 require_once
"Services/WebDAV/classes/Tools/_parse_propfind.php";
23 require_once
"Services/WebDAV/classes/Tools/_parse_proppatch.php";
24 require_once
"Services/WebDAV/classes/Tools/_parse_lockinfo.php";
128 $uri = (@$_SERVER[
"HTTPS"] ===
"on" ?
"https:" :
"http:");
129 $uri.=
"//$_SERVER[HTTP_HOST]$_SERVER[SCRIPT_NAME]";
131 $this->base_uri =
$uri;
132 $this->uri =
$uri . $_SERVER[PATH_INFO];
135 if (empty($this->dav_powered_by)) {
136 header(
"X-Dav-Powered-By: PHP class: ".get_class($this));
138 header(
"X-Dav-Powered-By: ".$this->dav_powered_by );
147 header(
'WWW-Authenticate: Basic realm="'.($this->http_auth_realm).
'"');
163 $this->path = $this->
_urldecode($_SERVER[
"PATH_INFO"]);
164 if (!strlen($this->path)) {
165 header(
"Location: ".$this->base_uri.
"/");
179 $method = strtolower($_SERVER[
"REQUEST_METHOD"]);
180 $wrapper =
"http_".$method;
183 if ($method ==
"head" && !method_exists($this,
"head")) {
187 if (method_exists($this, $wrapper) && ($method ==
"options" || method_exists($this, $method))) {
190 if ($_SERVER[
"REQUEST_METHOD"] ==
"LOCK") {
194 header(
"Allow: ".join(
", ", $this->
_allow()));
464 header(
"MS-Author-Via: DAV");
471 if (isset($allow[
'LOCK'])) {
477 header(
"DAV: " .join(
"," , $dav));
478 header(
"Allow: ".join(
", ", $allow));
480 header(
"Content-length: 0");
500 if (isset($_SERVER[
'HTTP_DEPTH'])) {
501 $options[
"depth"] = $_SERVER[
"HTTP_DEPTH"];
503 $options[
"depth"] =
"infinity";
508 if (!$propinfo->success) {
512 $options[
'props'] = $propinfo->props;
516 if (!$this->propfind($options,
$files)) {
525 $ns_defs =
"xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\"";
531 if (!isset(
$file[
"props"]) || !is_array(
$file[
"props"])) {
536 foreach(
$file[
"props"] as $key => $prop) {
541 switch($options[
'props']) {
549 unset(
$files[
"files"][$filekey][
"props"][$key][
"val"]);
556 foreach((array)$options[
"props"] as $reqprop) {
557 if ( $reqprop[
"name"] == $prop[
"name"]
558 && $reqprop[
"xmlns"] == $prop[
"ns"]) {
566 $files[
"files"][$filekey][
"props"][$key]=
"";
573 if (empty($prop[
"ns"]))
continue;
575 if ($ns ==
"DAV:")
continue;
576 if (isset($ns_hash[$ns]))
continue;
579 $ns_name =
"ns".(count($ns_hash) + 1);
580 $ns_hash[$ns] = $ns_name;
581 $ns_defs .=
" xmlns:$ns_name=\"$ns\"";
586 if (is_array($options[
'props'])) {
587 foreach($options[
"props"] as $reqprop) {
588 if($reqprop[
'name']==
"")
continue;
593 foreach(
$file[
"props"] as $prop) {
594 if ( $reqprop[
"name"] == $prop[
"name"]
595 && $reqprop[
"xmlns"] == $prop[
"ns"]) {
602 if($reqprop[
"xmlns"]===
"DAV:" && $reqprop[
"name"]===
"lockdiscovery") {
604 $files[
"files"][$filekey][
"props"][]
610 $files[
"files"][$filekey][
"noprops"][] =
611 $this->
mkprop($reqprop[
"xmlns"], $reqprop[
"name"],
"");
614 if ($reqprop[
"xmlns"] !=
"DAV:" && !isset($ns_hash[$reqprop[
"xmlns"]])) {
615 $ns_name =
"ns".(count($ns_hash) + 1);
616 $ns_hash[$reqprop[
"xmlns"]] = $ns_name;
617 $ns_defs .=
" xmlns:$ns_name=\"$reqprop[xmlns]\"";
627 header(
'Content-Type: text/xml; charset="utf-8"');
630 echo
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
631 echo
"<D:multistatus xmlns:D=\"DAV:\">\n";
635 if(!is_array($file) || empty($file) || !isset($file[
"path"]))
continue;
636 $path = $file[
'path'];
639 echo
" <D:response $ns_defs>\n";
643 $href = $_SERVER[
'SCRIPT_NAME'] .
$path;
646 echo
" <D:href>$href</D:href>\n";
649 if (isset($file[
"props"]) && is_array($file[
"props"])) {
650 echo
" <D:propstat>\n";
653 foreach($file[
"props"] as $key => $prop) {
655 if (!is_array($prop))
continue;
656 if (!isset($prop[
"name"]))
continue;
657 if (!isset($prop[
"val"]) || $prop[
"val"] ===
"" || $prop[
"val"] ===
false) {
659 if($prop[
"ns"]==
"DAV:") {
660 echo
" <D:$prop[name]/>\n";
661 }
else if(!empty($prop[
"ns"])) {
662 echo
" <".$ns_hash[$prop[
"ns"]].
":$prop[name]/>\n";
664 echo
" <$prop[name] xmlns=\"\"/>";
666 }
else if ($prop[
"ns"] ==
"DAV:") {
668 switch ($prop[
"name"]) {
670 echo
" <D:creationdate ns0:dt=\"dateTime.tz\">"
672 . gmdate(
"Y-m-d\\TH:i:s\\Z",$prop[
'val'])
675 .
"</D:creationdate>\n";
677 case "getlastmodified":
678 echo
" <D:getlastmodified ns0:dt=\"dateTime.rfc1123\">"
679 . gmdate(
"D, d M Y H:i:s ", $prop[
'val'])
680 .
"GMT</D:getlastmodified>\n";
683 echo
" <D:resourcetype><D:$prop[val]/></D:resourcetype>\n";
685 case "supportedlock":
686 echo
" <D:supportedlock>$prop[val]</D:supportedlock>\n";
688 case "lockdiscovery":
689 echo
" <D:lockdiscovery>\n";
691 echo
" </D:lockdiscovery>\n";
694 echo
" <D:$prop[name]>"
696 .
"</D:$prop[name]>\n";
702 echo
" <" . $ns_hash[$prop[
"ns"]] .
":$prop[name]>"
704 .
"</" . $ns_hash[$prop[
"ns"]] .
":$prop[name]>\n";
706 echo
" <$prop[name] xmlns=\"\">"
708 .
"</$prop[name]>\n";
714 echo
" <D:status>HTTP/1.1 200 OK</D:status>\n";
715 echo
" </D:propstat>\n";
719 if (isset($file[
"noprops"])) {
720 echo
" <D:propstat>\n";
723 foreach($file[
"noprops"] as $key => $prop) {
724 if ($prop[
"ns"] ==
"DAV:") {
725 echo
" <D:$prop[name]/>\n";
726 }
else if ($prop[
"ns"] ==
"") {
727 echo
" <$prop[name] xmlns=\"\"/>\n";
729 echo
" <" . $ns_hash[$prop[
"ns"]] .
":$prop[name]/>\n";
734 echo
" <D:status>HTTP/1.1 404 Not Found</D:status>\n";
735 echo
" </D:propstat>\n";
738 echo
" </D:response>\n";
741 echo
"</D:multistatus>\n";
763 if (!$propinfo->success) {
768 $options[
'props'] = $propinfo->props;
770 $responsedescr = $this->proppatch($options);
773 header(
'Content-Type: text/xml; charset="utf-8"');
775 echo
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
777 echo
"<D:multistatus xmlns:D=\"DAV:\">\n";
778 echo
" <D:response>\n";
779 echo
" <D:href>".$this->_urlencode($_SERVER[
"SCRIPT_NAME"].$this->path).
"</D:href>\n";
781 foreach($options[
"props"] as $prop) {
782 echo
" <D:propstat>\n";
783 echo
" <D:prop><$prop[name] xmlns=\"$prop[ns]\"/></D:prop>\n";
784 echo
" <D:status>HTTP/1.1 $prop[status]</D:status>\n";
785 echo
" </D:propstat>\n";
788 if ($responsedescr) {
789 echo
" <D:responsedescription>".
791 "</D:responsedescription>\n";
794 echo
" </D:response>\n";
795 echo
"</D:multistatus>\n";
817 $stat = $this->mkcol($options);
841 if (
true === ($status = $this->
get($options))) {
842 if (!headers_sent()) {
845 if (!isset($options[
'mimetype'])) {
846 $options[
'mimetype'] =
"application/octet-stream";
848 header(
"Content-type: $options[mimetype]");
850 if (isset($options[
'mtime'])) {
851 header(
"Last-modified:".gmdate(
"D, d M Y H:i:s ", $options[
'mtime']).
"GMT");
854 if (isset($options[
'stream'])) {
856 if (!empty($options[
'ranges']) && (0===fseek($options[
'stream'], 0, SEEK_SET))) {
859 if (count($options[
'ranges']) === 1) {
860 $range = $options[
'ranges'][0];
862 if (isset($range[
'start'])) {
863 fseek($options[
'stream'], $range[
'start'], SEEK_SET);
864 if (feof($options[
'stream'])) {
865 $this->
http_status(
"416 Requested range not satisfiable");
869 if (isset($range[
'end'])) {
870 $size = $range[
'end']-$range[
'start']+1;
872 header(
"Content-length: $size");
873 header(
"Content-range: $range[start]-$range[end]/"
874 . (isset($options[
'size']) ? $options[
'size'] :
"*"));
875 while (
$size && !feof($options[
'stream'])) {
876 $buffer = fread($options[
'stream'], 4096);
877 $size -= strlen($buffer);
882 if (isset($options[
'size'])) {
883 header(
"Content-length: ".($options[
'size'] - $range[
'start']));
884 header(
"Content-range: $start-$end/"
885 . (isset($options[
'size']) ? $options[
'size'] :
"*"));
887 fpassthru($options[
'stream']);
890 header(
"Content-length: ".$range[
'last']);
891 fseek($options[
'stream'], -$range[
'last'], SEEK_END);
892 fpassthru($options[
'stream']);
896 foreach ($options[
'ranges'] as $range) {
898 if (isset($range[
'start'])) {
899 $from = $range[
'start'];
900 $to = !empty($range[
'end']) ? $range[
'end'] : $options[
'size']-1;
902 $from = $options[
'size'] - $range[
'last']-1;
903 $to = $options[
'size'] -1;
905 $total = isset($options[
'size']) ? $options[
'size'] :
"*";
906 $size = $to - $from + 1;
910 fseek($options[
'stream'], $start, SEEK_SET);
911 while (
$size && !feof($options[
'stream'])) {
912 $buffer = fread($options[
'stream'], 4096);
913 $size -= strlen($buffer);
921 if (isset($options[
'size'])) {
922 header(
"Content-length: ".$options[
'size']);
929 while (! feof($options[
'stream'])) {
930 $buffer = fread($options[
'stream'], 4096);
937 } elseif (isset($options[
'data'])) {
938 if (is_array($options[
'data'])) {
941 header(
"Content-length: ".strlen($options[
'data']));
942 echo $options[
'data'];
948 if (
false === $status) {
950 $status =
'404 Not Found';
955 if (!headers_sent()) {
971 if (isset($_SERVER[
'HTTP_RANGE'])) {
974 if (ereg(
"bytes[[:space:]]*=[[:space:]]*(.+)", $_SERVER[
'HTTP_RANGE'], $matches)) {
975 $options[
"ranges"] = array();
978 foreach (explode(
",", $matches[1]) as $range) {
980 list($start, $end) = explode(
"-", $range);
981 $options[
"ranges"][] = ($start===
"")
982 ? array(
"last"=>$end)
983 : array(
"start"=>$start,
"end"=>$end);
1004 if ($mimetype ===
false) {
1005 if (!isset($this->multipart_separator)) {
1010 $this->multipart_separator =
"SEPARATOR_".md5(microtime());
1013 header(
"Content-type: multipart/byteranges; boundary=".$this->multipart_separator);
1018 echo
"\n--{$this->multipart_separator}--";
1022 echo
"\n--{$this->multipart_separator}\n";
1023 echo
"Content-type: $mimetype\n";
1024 echo
"Content-range: $from-$to/". (
$total ===
false ?
"*" :
$total);
1047 if (method_exists($this,
"HEAD")) {
1048 $status = $this->head($options);
1049 }
else if (method_exists($this,
"GET")) {
1051 $status = $this->GET($options);
1055 if($status===
true) $status =
"200 OK";
1056 if($status===
false) $status =
"404 Not found";
1076 $options[
"content_length"] = $_SERVER[
"CONTENT_LENGTH"];
1079 if (isset($_SERVER[
"CONTENT_TYPE"])) {
1081 if (!strncmp($_SERVER[
"CONTENT_TYPE"],
"multipart/", 10)) {
1083 echo
"The service does not support mulipart PUT requests";
1086 $options[
"content_type"] = $_SERVER[
"CONTENT_TYPE"];
1089 $options[
"content_type"] =
"application/octet-stream";
1097 foreach ($_SERVER as $key => $val) {
1098 if (strncmp($key,
"HTTP_CONTENT", 11))
continue;
1100 case 'HTTP_CONTENT_ENCODING':
1103 echo
"The service does not support '$val' content encoding";
1106 case 'HTTP_CONTENT_LANGUAGE':
1109 $options[
"content_language"] = $value;
1112 case 'HTTP_CONTENT_LOCATION':
1118 case 'HTTP_CONTENT_RANGE':
1122 if (!preg_match(
'@bytes\s+(\d+)-(\d+)/((\d+)|\*)@', $value, $matches)) {
1124 echo
"The service does only support single byte ranges";
1128 $range = array(
"start"=>$matches[1],
"end"=>$matches[2]);
1129 if (is_numeric($matches[3])) {
1130 $range[
"total_length"] = $matches[3];
1132 $option[
"ranges"][] = $range;
1139 case 'HTTP_CONTENT_MD5':
1142 echo
"The service does not support content MD5 checksum verification";
1148 echo
"The service does not support '$key'";
1153 $options[
"stream"] = fopen(
"php://input",
"r");
1155 $stat = $this->PUT($options);
1157 if ($stat ==
false) {
1158 $stat =
"403 Forbidden";
1159 }
else if (is_resource($stat) && get_resource_type($stat) ==
"stream") {
1162 $stat = $options[
"new"] ?
"201 Created" :
"204 No Content";
1164 if (!empty($options[
"ranges"])) {
1166 if (0 == fseek($stream, $range[0][
"start"], SEEK_SET)) {
1167 $length = $range[0][
"end"]-$range[0][
"start"]+1;
1168 if (!fwrite($stream, fread($options[
"stream"], $length))) {
1169 $stat =
"403 Forbidden";
1172 $stat =
"403 Forbidden";
1175 while (!feof($options[
"stream"])) {
1177 if (
false === ($written = fwrite($stream, fread($options[
"stream"], 4096)))) {
1179 $stat =
"403 Forbidden";
1189 $this->PUTfinished($options);
1213 if (isset($_SERVER[
"HTTP_DEPTH"])) {
1214 if ($_SERVER[
"HTTP_DEPTH"] !=
"infinity") {
1226 $stat = $this->
delete($options);
1290 if (isset($_SERVER[
'HTTP_DEPTH'])) {
1291 $options[
"depth"] = $_SERVER[
"HTTP_DEPTH"];
1293 $options[
"depth"] =
"infinity";
1296 if (isset($_SERVER[
"HTTP_TIMEOUT"])) {
1297 $options[
"timeout"] = explode(
",", $_SERVER[
"HTTP_TIMEOUT"]);
1300 if(empty($_SERVER[
'CONTENT_LENGTH']) && !empty($_SERVER[
'HTTP_IF'])) {
1308 $options[
"update"] = substr($_SERVER[
'HTTP_IF'], 2, -2);
1309 $stat = $this->lock($options);
1313 if (!$lockinfo->success) {
1324 $options[
"scope"] = $lockinfo->lockscope;
1325 $options[
"type"] = $lockinfo->locktype;
1326 $options[
"owner"] = $lockinfo->owner;
1330 $stat = $this->lock($options);
1333 if(is_bool($stat)) {
1334 $http_stat = $stat ?
"200 OK" :
"423 Locked";
1341 if ($http_stat{0} == 2) {
1342 if($options[
"timeout"]) {
1345 if($options[
"timeout"]>1000000) {
1346 $timeout =
"Second-".($options[
'timeout']-time());
1348 $timeout =
"Second-$options[timeout]";
1351 $timeout =
"Infinite";
1371 header(
'Content-Type: text/xml; charset="utf-8"');
1372 header(
"Lock-Token: <$options[locktoken]>");
1373 echo
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
1374 echo
"<D:prop xmlns:D=\"DAV:\">\n";
1375 echo
" <D:lockdiscovery>\n";
1376 echo
" <D:activelock>\n";
1377 echo
" <D:lockscope><D:$options[scope]/></D:lockscope>\n";
1378 echo
" <D:locktype><D:$options[type]/></D:locktype>\n";
1379 echo
" <D:depth>$options[depth]</D:depth>\n";
1380 echo
" <D:owner>$options[owner]</D:owner>\n";
1381 echo
" <D:timeout>$timeout</D:timeout>\n";
1382 echo
" <D:locktoken><D:href>$options[locktoken]</D:href></D:locktoken>\n";
1383 echo
" </D:activelock>\n";
1384 echo
" </D:lockdiscovery>\n";
1385 echo
"</D:prop>\n\n";
1405 if (isset($_SERVER[
'HTTP_DEPTH'])) {
1406 $options[
"depth"] = $_SERVER[
"HTTP_DEPTH"];
1408 $options[
"depth"] =
"infinity";
1412 $options[
"token"] = substr(trim($_SERVER[
"HTTP_LOCK_TOKEN"]), 1, -1);
1415 $stat = $this->unlock($options);
1432 if (isset($_SERVER[
"HTTP_DEPTH"])) {
1433 $options[
"depth"] = $_SERVER[
"HTTP_DEPTH"];
1435 $options[
"depth"] =
"infinity";
1438 extract(parse_url($_SERVER[
"HTTP_DESTINATION"]));
1444 if (isset($port) && $port != 80)
1445 $http_host.=
":$port";
1447 list($http_header_host,$http_header_port) = explode(
":",$_SERVER[
"HTTP_HOST"]);
1448 if (isset($http_header_port) && $http_header_port != 80) {
1449 $http_header_host .=
":".$http_header_port;
1452 if ($http_host == $http_header_host &&
1453 !strncmp($_SERVER[
"SCRIPT_NAME"],
$path,
1454 strlen($_SERVER[
"SCRIPT_NAME"]))) {
1455 $options[
"dest"] = substr(
$path, strlen($_SERVER[
"SCRIPT_NAME"]));
1465 $options[
"dest_url"] = $_SERVER[
"HTTP_DESTINATION"];
1469 if (isset($_SERVER[
"HTTP_OVERWRITE"])) {
1470 $options[
"overwrite"] = $_SERVER[
"HTTP_OVERWRITE"] ==
"T";
1472 $options[
"overwrite"] =
true;
1475 $stat = $this->$what($options);
1492 $allow = array(
"OPTIONS" =>
"OPTIONS");
1497 foreach(get_class_methods($this) as $method) {
1498 if (!strncmp(
"http_", $method, 5)) {
1499 $method = strtoupper(substr($method, 5));
1500 if (method_exists($this, $method)) {
1501 $allow[$method] = $method;
1507 if (isset($allow[
"GET"]))
1508 $allow[
"HEAD"] =
"HEAD";
1511 if (!method_exists($this,
"checklock")) {
1512 unset($allow[
"LOCK"]);
1513 unset($allow[
"UNLOCK"]);
1531 $args = func_get_args();
1532 if (count($args) == 3) {
1533 return array(
"ns" => $args[0],
1537 return array(
"ns" =>
"DAV:",
1553 if (method_exists($this,
"checkAuth")) {
1555 return $this->checkAuth(@$_SERVER[
"AUTH_TYPE"],
1556 @$_SERVER[
"PHP_AUTH_USER"],
1557 @$_SERVER[
"PHP_AUTH_PW"]);
1558 }
else if (method_exists($this,
"check_auth")) {
1560 return $this->check_auth(@$_SERVER[
"AUTH_TYPE"],
1561 @$_SERVER[
"PHP_AUTH_USER"],
1562 @$_SERVER[
"PHP_AUTH_PW"]);
1582 if (function_exists(
"uuid_create")) {
1583 return uuid_create();
1587 $uuid = md5(microtime().getmypid());
1591 $n = 8 + (ord($uuid{16}) & 3);
1592 $hex =
"0123456789abcdef";
1593 $uuid{16} = $hex{
$n};
1596 return substr($uuid, 0, 8).
"-"
1597 . substr($uuid, 8, 4).
"-"
1598 . substr($uuid, 12, 4).
"-"
1599 . substr($uuid, 16, 4).
"-"
1600 . substr($uuid, 20);
1611 return "opaquelocktoken:".$this->_new_uuid();
1628 while (ctype_space($string{$pos})) {
1633 if (strlen($string) <= $pos) {
1638 $c = $string{$pos++};
1644 $pos2 = strpos($string,
">", $pos);
1645 $uri = substr($string, $pos, $pos2 - $pos);
1647 return array(
"URI",
$uri);
1651 if ($string{$pos} ==
"W") {
1652 $type =
"ETAG_WEAK";
1655 $type =
"ETAG_STRONG";
1657 $pos2 = strpos($string,
"]", $pos);
1658 $etag = substr($string, $pos + 1, $pos2 - $pos - 2);
1660 return array($type, $etag);
1665 return array(
"NOT",
"Not");
1669 return array(
"CHAR", $c);
1682 $len = strlen($str);
1687 while ($pos < $len) {
1692 if ($token[0] ==
"URI") {
1700 if ($token[0] !=
"CHAR" || $token[1] !=
"(") {
1709 if ($token[0] ==
"NOT") {
1713 switch ($token[0]) {
1715 switch ($token[1]) {
1728 $list[] = $not.
"<$token[1]>";
1732 $list[] = $not.
"[W/'$token[1]']>";
1736 $list[] = $not.
"['$token[1]']>";
1745 if (@is_array($uris[
$uri])) {
1746 $uris[
$uri] = array_merge($uris[$uri],$list);
1748 $uris[
$uri] = $list;
1766 if (isset($_SERVER[
"HTTP_IF"])) {
1767 $this->_if_header_uris =
1770 foreach($this->_if_header_uris as
$uri => $conditions) {
1776 foreach($conditions as $condition) {
1780 if (!strncmp($condition,
"<opaquelocktoken:", strlen(
"<opaquelocktoken"))) {
1781 if (!ereg(
"^<opaquelocktoken:[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}>$", $condition)) {
1792 if ($state ==
true) {
1828 if (method_exists($this,
"checkLock")) {
1830 $lock = $this->checkLock(
$path);
1833 if (is_array($lock) && count($lock)) {
1835 if (!strstr($_SERVER[
"HTTP_IF"], $lock[
"token"])) {
1836 if (!$exclusive_only || ($lock[
"scope"] !==
"shared"))
1857 if (!method_exists($this,
"checklock")) {
1865 $lock = $this->checklock(
$path);
1868 if (is_array($lock) && count($lock)) {
1870 if (!empty($lock[
"expires"])) {
1871 $timeout =
"Second-".($lock[
"expires"] - time());
1872 }
else if (!empty($lock[
"timeout"])) {
1873 $timeout =
"Second-$lock[timeout]";
1875 $timeout =
"Infinite";
1881 <D:lockscope><D:$lock[scope]/></D:lockscope>
1882 <D:locktype><D:$lock[type]/></D:locktype>
1883 <D:depth>$lock[depth]</D:depth>
1884 <D:owner>$lock[owner]</D:owner>
1885 <D:timeout>$timeout</D:timeout>
1886 <D:locktoken><D:href>$lock[token]</D:href></D:locktoken>
1893 return $activelocks;
1905 if($status ===
true) {
1911 $this->_http_status = $status;
1914 header(
"HTTP/1.1 $status");
1915 header(
"X-WebDAV-Status: $status",
true);
1929 return strtr($url, array(
" "=>
"%20",
1964 switch (strtolower($this->_prop_encoding)) {
1971 return utf8_encode($text);
1996 global
$log, $ilias;
1998 $ilias->account->getLogin()
1999 .
' DAV Server.'.str_replace(
"\n",
";",$message)