Compare commits
306 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9cd3e3b9e9 | |||
| a5a25eb2a8 | |||
| db30d8621e | |||
| ad9420f7fd | |||
| db7ca534c6 | |||
| 727d95f091 | |||
| d8a596cb00 | |||
| ca6aa13b40 | |||
| 09115c3cda | |||
| a0b3b65fa3 | |||
| 73666ae123 | |||
| 8437dea9ff | |||
| 1bbaea5fce | |||
| 62cc311210 | |||
| eda47816bd | |||
| 9db23b27fd | |||
| 23a5c2887e | |||
| 430ac501e0 | |||
| d5328585dd | |||
| 9fb1746ff9 | |||
| b0a81b5b0d | |||
| f2eef0ccf8 | |||
| 5f30c84cd4 | |||
| c035fe4cbf | |||
| c50bbc8c04 | |||
| 35a44a6b1c | |||
| c99348113a | |||
| 81578371f8 | |||
| 0e28a6675d | |||
| db946256f9 | |||
| 5bf961b06a | |||
| 253e5f3cff | |||
| 5bf0ede3ef | |||
| 3a5271dd2e | |||
| 52b1f7ea66 | |||
| 57780bfa37 | |||
| 78c2a21836 | |||
| eb92c9bd1b | |||
| 58347e3510 | |||
| 2cdc7b81f1 | |||
| df49bb780b | |||
| d35a22c763 | |||
| 7858ee8896 | |||
| f417741ac9 | |||
| 9fe48e41f8 | |||
| d0142ea1fb | |||
| 01a8af1a1c | |||
| 0516e936db | |||
| af83a62ec5 | |||
| 2e7731cc7b | |||
| c0d45c890f | |||
| 058918d101 | |||
| bb8a274848 | |||
| 9e05781ec2 | |||
| f96405e78a | |||
| 8a1145f607 | |||
| 39dbecdc10 | |||
| 3401cb5358 | |||
| 3bb0f45b9b | |||
| da5fd1a3d0 | |||
| 144a435967 | |||
| c0a8e3f436 | |||
| 2f21225155 | |||
| ea7b980255 | |||
| 395eace356 | |||
| cc948fe354 | |||
| 1a2fad128b | |||
| 67682ec259 | |||
| c840a688ab | |||
| 3ede33a886 | |||
| 4d7910f424 | |||
| 10d97c8140 | |||
| d57b870f3e | |||
| 44119e2051 | |||
| 8596226787 | |||
| 85382a5140 | |||
| 1f4713d320 | |||
| b7dd48b41f | |||
| 4decc86598 | |||
| 6fb5095197 | |||
| 79a7ee656e | |||
| 71679c8921 | |||
| 44dbdd9632 | |||
| 97231e64ba | |||
| cc785e2f1b | |||
| a9f041a702 | |||
| 5daf512405 | |||
| d6bc7757ab | |||
| 94db6c64a9 | |||
| ef159cd863 | |||
| 263da2463a | |||
| 15a485cbdb | |||
| 440828f0f1 | |||
| 5d53e0d5ce | |||
| 07c0cda12d | |||
| 2f08d24743 | |||
| 1b4f249157 | |||
| 410d798e98 | |||
| 34937479a8 | |||
| 41bfd5e1f3 | |||
| e56de16876 | |||
| f385d32331 | |||
| 3c5470358e | |||
| 05db74e7db | |||
| 470e93e4df | |||
| f359c2a716 | |||
| 88516dd8ae | |||
| 3e20032a32 | |||
| f849dd0693 | |||
| a566684564 | |||
| dceb2b7c32 | |||
| 270d1199a6 | |||
| 89bdb78f0a | |||
| 756424b6dd | |||
| e9c710e4fc | |||
| 8f2209680a | |||
| 95cee0eb5d | |||
| ea54fe98f7 | |||
| 939470d771 | |||
| 84754d3d20 | |||
| dd694b5fb4 | |||
| e44e357381 | |||
| ced12cbf76 | |||
| 2854ee56e9 | |||
| fd71023dd6 | |||
| 124e4ba53c | |||
| 85a0ba28d7 | |||
| 54352fe566 | |||
| 326496ff80 | |||
| 6188f07c95 | |||
| 4fa86c4dc3 | |||
| 39a54f5abf | |||
| 52dd0274d3 | |||
| 3ed0960edb | |||
| a12d3834d4 | |||
| 780f2293d6 | |||
| f9c5a0fd4d | |||
| a575e86b88 | |||
| 8f501a928a | |||
| ad762980bb | |||
| b019a57894 | |||
| 8724fe4b11 | |||
| b1b1fe72e8 | |||
| bfff3d3f9b | |||
| cb0666e235 | |||
| cb55229c1e | |||
| 9b1f2462bf | |||
| 3fab16603a | |||
| 66343f977f | |||
| bcb9cf3c06 | |||
| 55d8057b7f | |||
| 5e19854d47 | |||
| 781b579074 | |||
| 77c07615f8 | |||
| 743d01d4a6 | |||
| 12cd67b8d9 | |||
| 6641af720d | |||
| 2d110f25f7 | |||
| 39b6bb8a18 | |||
| 7270be85a4 | |||
| 560d87e26a | |||
| b3245ac327 | |||
| a1a44a3582 | |||
| da5c30efa2 | |||
| 1ffcd33817 | |||
| 9e0a6d86ba | |||
| 501bb0afd6 | |||
| 5f7d053c3a | |||
| 56c8976bac | |||
| 72d6c3246f | |||
| 166edb2cc1 | |||
| 8b31081c52 | |||
| 4619c662cc | |||
| e8a0ceacaf | |||
| 4802f21a9e | |||
| 9c88857364 | |||
| b71cc08ce1 | |||
| 0741598f58 | |||
| e29b0d099f | |||
| 3fde72ea5c | |||
| d022b89063 | |||
| 5b8155a578 | |||
| b7a50a4f6f | |||
| a606131a6a | |||
| 6b413b0d0f | |||
| 693c535a94 | |||
| a25cf8ba83 | |||
| a15a99b304 | |||
| 6e8f970999 | |||
| bbe0cf376f | |||
| f660247b47 | |||
| 1d2d2cf261 | |||
| 50d5ca71d0 | |||
| 189e8ab1e0 | |||
| dbbbfd4b2b | |||
| ece4a843c0 | |||
| d62f138153 | |||
| 7fc1276ac7 | |||
| ba2bba0f66 | |||
| ab7561b2b6 | |||
| 3740ce2854 | |||
| bfd53c5bd7 | |||
| 9691d56713 | |||
| 92829e8f94 | |||
| c518f35e83 | |||
| 3e57a44829 | |||
| 5cf1fd8aa9 | |||
| c64f579518 | |||
| 054c168b32 | |||
| f599267459 | |||
| 3cd416b667 | |||
| 3139636906 | |||
| 0d349e331e | |||
| 51968cfd53 | |||
| 21488bdd7e | |||
| 3945f9cdb1 | |||
| de1b95c8e7 | |||
| 725e733178 | |||
| d226ed697e | |||
| 77b57fbbfe | |||
| 0dc3ffd29a | |||
| 10e45481be | |||
| bfb8436ca2 | |||
| edf3503779 | |||
| a98cfbe868 | |||
| 12ea922389 | |||
| db6fc916cf | |||
| 46e9bf5678 | |||
| c6177d2629 | |||
| 0399a88eb6 | |||
| 8f715e12a9 | |||
| 4b39ce5134 | |||
| 53ae74200a | |||
| 9f570345a5 | |||
| 5d866295d8 | |||
| 9eae10b94a | |||
| ca58aa1644 | |||
| 3b9c10dcf6 | |||
| 28e0fa7d1d | |||
| 3833f2315a | |||
| e65c3ef9c9 | |||
| 552aee93fa | |||
| 1791fbdc49 | |||
| c2e3999f76 | |||
| 677cec6e1c | |||
| 7435064cd3 | |||
| 0c57d94467 | |||
| 366aeb7228 | |||
| 296884b24a | |||
| 2e5ce9f4ec | |||
| cc67ae9dbb | |||
| 71d33fa065 | |||
| db3b0b63da | |||
| 5433932bd4 | |||
| f5c6a22f17 | |||
| f47c64cec6 | |||
| 7feb0f737b | |||
| 5271c1a9ad | |||
| ef3e5899c6 | |||
| badd2908b7 | |||
| 3f3b92a149 | |||
| c3646f5554 | |||
| a97d73d616 | |||
| 50684a5a34 | |||
| f06467b95b | |||
| 9faae4b71c | |||
| e49d5a5f9a | |||
| ed10a5de5b | |||
| e8b84145e8 | |||
| 38f8734014 | |||
| a10564e214 | |||
| ecef3b6b98 | |||
| e65ea6a8b7 | |||
| 7139de2a6e | |||
| b5403de5e5 | |||
| 0966f1358b | |||
| a0ac64cbd6 | |||
| b03b6dfb99 | |||
| c11f9833ac | |||
| 9ee34ef6b3 | |||
| df7e519159 | |||
| 5e60812ad4 | |||
| 1263604703 | |||
| 5904db580f | |||
| 1960067926 | |||
| 33bd9ecd9d | |||
| 7f7c1fcccf | |||
| 34fdd0e839 | |||
| 9de4eccd99 | |||
| a0847dc852 | |||
| 87a3145ba1 | |||
| 85e236d798 | |||
| cb4c3d7a9e | |||
| e55fc87ad3 | |||
| 5398dea0df | |||
| e0eb6bbd28 | |||
| 822b323f8e | |||
| c1f645cd5f | |||
| f1d9359acf | |||
| 550e774db2 | |||
| e23b06ec8c | |||
| 4f8b8a8a59 | |||
| c06d71e662 | |||
| cce43652f0 | |||
| 9f0a4c8edb | |||
| f571cfbf71 |
@@ -19,4 +19,8 @@ RewriteRule ^apps/contacts/carddav.php remote.php/carddav/ [QSA,L]
|
||||
RewriteRule ^apps/([^/]*)/(.*\.(css|php))$ index.php?app=$1&getfile=$2 [QSA,L]
|
||||
RewriteRule ^remote/(.*) remote.php [QSA,L]
|
||||
</IfModule>
|
||||
<IfModule mod_mime.c>
|
||||
AddType image/svg+xml svg svgz
|
||||
AddEncoding gzip svgz
|
||||
</IfModule>
|
||||
Options -Indexes
|
||||
|
||||
+10
-1
@@ -363,6 +363,7 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
|
||||
return MDB2_OK;
|
||||
}
|
||||
|
||||
$unquoted_name = $name;
|
||||
$name = $db->quoteIdentifier($name, true);
|
||||
|
||||
if (!empty($changes['remove']) && is_array($changes['remove'])) {
|
||||
@@ -398,6 +399,7 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
|
||||
|
||||
if (!empty($changes['change']) && is_array($changes['change'])) {
|
||||
foreach ($changes['change'] as $field_name => $field) {
|
||||
$unquoted_field_name = $field_name;
|
||||
$field_name = $db->quoteIdentifier($field_name, true);
|
||||
if (!empty($field['definition']['type'])) {
|
||||
$server_info = $db->getServerVersion();
|
||||
@@ -419,7 +421,14 @@ class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
if (array_key_exists('default', $field['definition'])) {
|
||||
if (array_key_exists('autoincrement', $field['definition'])) {
|
||||
$query = "ALTER $field_name SET DEFAULT nextval(".$db->quote($unquoted_name.'_'.$unquoted_field_name.'_seq', 'text').")";
|
||||
$result = $db->exec("ALTER TABLE $name $query");
|
||||
if (PEAR::isError($result)) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
elseif (array_key_exists('default', $field['definition'])) {
|
||||
$query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
|
||||
$result = $db->exec("ALTER TABLE $name $query");
|
||||
if (PEAR::isError($result)) {
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* FullCalendar v1.5.3 Stylesheet
|
||||
* FullCalendar v1.5.4 Stylesheet
|
||||
*
|
||||
* Copyright (c) 2011 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Mon Feb 6 22:40:40 2012 -0800
|
||||
* Date: Tue Sep 4 23:38:33 2012 -0700
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* FullCalendar v1.5.3 Print Stylesheet
|
||||
* FullCalendar v1.5.4 Print Stylesheet
|
||||
*
|
||||
* Include this stylesheet on your page to get a more printer-friendly calendar.
|
||||
* When including this stylesheet, use the media='print' attribute of the <link> tag.
|
||||
@@ -9,7 +9,7 @@
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Mon Feb 6 22:40:40 2012 -0800
|
||||
* Date: Tue Sep 4 23:38:33 2012 -0700
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+17
-21
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @preserve
|
||||
* FullCalendar v1.5.3
|
||||
* FullCalendar v1.5.4
|
||||
* http://arshaw.com/fullcalendar/
|
||||
*
|
||||
* Use fullcalendar.css for basic styling.
|
||||
@@ -11,7 +11,7 @@
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Mon Feb 6 22:40:40 2012 -0800
|
||||
* Date: Tue Sep 4 23:38:33 2012 -0700
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -111,7 +111,7 @@ var rtlDefaults = {
|
||||
|
||||
|
||||
|
||||
var fc = $.fullCalendar = { version: "1.5.3" };
|
||||
var fc = $.fullCalendar = { version: "1.5.4" };
|
||||
var fcViews = fc.views = {};
|
||||
|
||||
|
||||
@@ -1658,7 +1658,7 @@ function sliceSegs(events, visEventEnds, start, end) {
|
||||
msLength: segEnd - segStart
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return segs.sort(segCmp);
|
||||
}
|
||||
|
||||
@@ -1742,29 +1742,26 @@ function setOuterHeight(element, height, includeMargins) {
|
||||
}
|
||||
|
||||
|
||||
// TODO: curCSS has been deprecated (jQuery 1.4.3 - 10/16/2010)
|
||||
|
||||
|
||||
function hsides(element, includeMargins) {
|
||||
return hpadding(element) + hborders(element) + (includeMargins ? hmargins(element) : 0);
|
||||
}
|
||||
|
||||
|
||||
function hpadding(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'paddingLeft', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'paddingRight', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'paddingLeft', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'paddingRight', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function hmargins(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'marginLeft', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'marginRight', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'marginLeft', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'marginRight', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function hborders(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'borderLeftWidth', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'borderRightWidth', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'borderLeftWidth', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'borderRightWidth', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1774,20 +1771,20 @@ function vsides(element, includeMargins) {
|
||||
|
||||
|
||||
function vpadding(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'paddingTop', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'paddingBottom', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'paddingTop', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'paddingBottom', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function vmargins(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'marginTop', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'marginBottom', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'marginTop', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'marginBottom', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
function vborders(element) {
|
||||
return (parseFloat($.curCSS(element[0], 'borderTopWidth', true)) || 0) +
|
||||
(parseFloat($.curCSS(element[0], 'borderBottomWidth', true)) || 0);
|
||||
return (parseFloat($.css(element[0], 'borderTopWidth', true)) || 0) +
|
||||
(parseFloat($.css(element[0], 'borderBottomWidth', true)) || 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1956,7 +1953,6 @@ function firstDefined() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fcViews.month = MonthView;
|
||||
|
||||
function MonthView(element, calendar) {
|
||||
@@ -4662,7 +4658,7 @@ function DayEventRenderer() {
|
||||
"</span>";
|
||||
}
|
||||
html +=
|
||||
"<span class='fc-event-title'>" + event.title + "</span>" +
|
||||
"<span class='fc-event-title'>" + htmlEscape(event.title) + "</span>" +
|
||||
"</div>";
|
||||
if (seg.isEnd && isEventResizable(event)) {
|
||||
html +=
|
||||
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
|
||||
FullCalendar v1.5.3
|
||||
FullCalendar v1.5.4
|
||||
http://arshaw.com/fullcalendar/
|
||||
|
||||
Use fullcalendar.css for basic styling.
|
||||
@@ -11,7 +11,7 @@
|
||||
Dual licensed under the MIT and GPL licenses, located in
|
||||
MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
|
||||
Date: Mon Feb 6 22:40:40 2012 -0800
|
||||
Date: Tue Sep 4 23:38:33 2012 -0700
|
||||
|
||||
*/
|
||||
(function(m,ma){function wb(a){m.extend(true,Ya,a)}function Yb(a,b,e){function d(k){if(E){u();q();na();S(k)}else f()}function f(){B=b.theme?"ui":"fc";a.addClass("fc");b.isRTL&&a.addClass("fc-rtl");b.theme&&a.addClass("ui-widget");E=m("<div class='fc-content' style='position:relative'/>").prependTo(a);C=new Zb(X,b);(P=C.render())&&a.prepend(P);y(b.defaultView);m(window).resize(oa);t()||g()}function g(){setTimeout(function(){!n.start&&t()&&S()},0)}function l(){m(window).unbind("resize",oa);C.destroy();
|
||||
@@ -39,10 +39,10 @@ a[12])*1E3);lb(e,b)}else{e.setUTCFullYear(a[1],a[3]?a[3]-1:0,a[5]||1);e.setUTCHo
|
||||
10):0)}}function Oa(a,b,e){return ib(a,null,b,e)}function ib(a,b,e,d){d=d||Ya;var f=a,g=b,l,j=e.length,t,y,S,Q="";for(l=0;l<j;l++){t=e.charAt(l);if(t=="'")for(y=l+1;y<j;y++){if(e.charAt(y)=="'"){if(f){Q+=y==l+1?"'":e.substring(l+1,y);l=y}break}}else if(t=="(")for(y=l+1;y<j;y++){if(e.charAt(y)==")"){l=Oa(f,e.substring(l+1,y),d);if(parseInt(l.replace(/\D/,""),10))Q+=l;l=y;break}}else if(t=="[")for(y=l+1;y<j;y++){if(e.charAt(y)=="]"){t=e.substring(l+1,y);l=Oa(f,t,d);if(l!=Oa(g,t,d))Q+=l;l=y;break}}else if(t==
|
||||
"{"){f=b;g=a}else if(t=="}"){f=a;g=b}else{for(y=j;y>l;y--)if(S=dc[e.substring(l,y)]){if(f)Q+=S(f,d);l=y-1;break}if(y==l)if(f)Q+=t}}return Q}function Ua(a){return a.end?ec(a.end,a.allDay):ba(N(a.start),1)}function ec(a,b){a=N(a);return b||a.getHours()||a.getMinutes()?ba(a,1):Ka(a)}function fc(a,b){return(b.msLength-a.msLength)*100+(a.event.start-b.event.start)}function Cb(a,b){return a.end>b.start&&a.start<b.end}function nb(a,b,e,d){var f=[],g,l=a.length,j,t,y,S,Q;for(g=0;g<l;g++){j=a[g];t=j.start;
|
||||
y=b[g];if(y>e&&t<d){if(t<e){t=N(e);S=false}else{t=t;S=true}if(y>d){y=N(d);Q=false}else{y=y;Q=true}f.push({event:j,start:t,end:y,isStart:S,isEnd:Q,msLength:y-t})}}return f.sort(fc)}function ob(a){var b=[],e,d=a.length,f,g,l,j;for(e=0;e<d;e++){f=a[e];for(g=0;;){l=false;if(b[g])for(j=0;j<b[g].length;j++)if(Cb(b[g][j],f)){l=true;break}if(l)g++;else break}if(b[g])b[g].push(f);else b[g]=[f]}return b}function Db(a,b,e){a.unbind("mouseover").mouseover(function(d){for(var f=d.target,g;f!=this;){g=f;f=f.parentNode}if((f=
|
||||
g._fci)!==ma){g._fci=ma;g=b[f];e(g.event,g.element,g);m(d.target).trigger(d)}d.stopPropagation()})}function Va(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.width(Math.max(0,b-pb(f,e)))}}function Eb(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.height(Math.max(0,b-Sa(f,e)))}}function pb(a,b){return gc(a)+hc(a)+(b?ic(a):0)}function gc(a){return(parseFloat(m.curCSS(a[0],"paddingLeft",true))||0)+(parseFloat(m.curCSS(a[0],"paddingRight",true))||0)}function ic(a){return(parseFloat(m.curCSS(a[0],
|
||||
"marginLeft",true))||0)+(parseFloat(m.curCSS(a[0],"marginRight",true))||0)}function hc(a){return(parseFloat(m.curCSS(a[0],"borderLeftWidth",true))||0)+(parseFloat(m.curCSS(a[0],"borderRightWidth",true))||0)}function Sa(a,b){return jc(a)+kc(a)+(b?Fb(a):0)}function jc(a){return(parseFloat(m.curCSS(a[0],"paddingTop",true))||0)+(parseFloat(m.curCSS(a[0],"paddingBottom",true))||0)}function Fb(a){return(parseFloat(m.curCSS(a[0],"marginTop",true))||0)+(parseFloat(m.curCSS(a[0],"marginBottom",true))||0)}
|
||||
function kc(a){return(parseFloat(m.curCSS(a[0],"borderTopWidth",true))||0)+(parseFloat(m.curCSS(a[0],"borderBottomWidth",true))||0)}function Za(a,b){b=typeof b=="number"?b+"px":b;a.each(function(e,d){d.style.cssText+=";min-height:"+b+";_height:"+b})}function xb(){}function Gb(a,b){return a-b}function Hb(a){return Math.max.apply(Math,a)}function Pa(a){return(a<10?"0":"")+a}function jb(a,b){if(a[b]!==ma)return a[b];b=b.split(/(?=[A-Z])/);for(var e=b.length-1,d;e>=0;e--){d=a[b[e].toLowerCase()];if(d!==
|
||||
ma)return d}return a[""]}function Qa(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function Ib(a){return a.id+"/"+a.className+"/"+a.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig,"")}function qb(a){a.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})}function ab(a){a.children().removeClass("fc-first fc-last").filter(":first-child").addClass("fc-first").end().filter(":last-child").addClass("fc-last")}
|
||||
g._fci)!==ma){g._fci=ma;g=b[f];e(g.event,g.element,g);m(d.target).trigger(d)}d.stopPropagation()})}function Va(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.width(Math.max(0,b-pb(f,e)))}}function Eb(a,b,e){for(var d=0,f;d<a.length;d++){f=m(a[d]);f.height(Math.max(0,b-Sa(f,e)))}}function pb(a,b){return gc(a)+hc(a)+(b?ic(a):0)}function gc(a){return(parseFloat(m.css(a[0],"paddingLeft",true))||0)+(parseFloat(m.css(a[0],"paddingRight",true))||0)}function ic(a){return(parseFloat(m.css(a[0],"marginLeft",
|
||||
true))||0)+(parseFloat(m.css(a[0],"marginRight",true))||0)}function hc(a){return(parseFloat(m.css(a[0],"borderLeftWidth",true))||0)+(parseFloat(m.css(a[0],"borderRightWidth",true))||0)}function Sa(a,b){return jc(a)+kc(a)+(b?Fb(a):0)}function jc(a){return(parseFloat(m.css(a[0],"paddingTop",true))||0)+(parseFloat(m.css(a[0],"paddingBottom",true))||0)}function Fb(a){return(parseFloat(m.css(a[0],"marginTop",true))||0)+(parseFloat(m.css(a[0],"marginBottom",true))||0)}function kc(a){return(parseFloat(m.css(a[0],
|
||||
"borderTopWidth",true))||0)+(parseFloat(m.css(a[0],"borderBottomWidth",true))||0)}function Za(a,b){b=typeof b=="number"?b+"px":b;a.each(function(e,d){d.style.cssText+=";min-height:"+b+";_height:"+b})}function xb(){}function Gb(a,b){return a-b}function Hb(a){return Math.max.apply(Math,a)}function Pa(a){return(a<10?"0":"")+a}function jb(a,b){if(a[b]!==ma)return a[b];b=b.split(/(?=[A-Z])/);for(var e=b.length-1,d;e>=0;e--){d=a[b[e].toLowerCase()];if(d!==ma)return d}return a[""]}function Qa(a){return a.replace(/&/g,
|
||||
"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function Ib(a){return a.id+"/"+a.className+"/"+a.style.cssText.replace(/(^|;)\s*(top|left|width|height)\s*:[^;]*/ig,"")}function qb(a){a.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})}function ab(a){a.children().removeClass("fc-first fc-last").filter(":first-child").addClass("fc-first").end().filter(":last-child").addClass("fc-last")}
|
||||
function rb(a,b){a.each(function(e,d){d.className=d.className.replace(/^fc-\w*/,"fc-"+lc[b.getDay()])})}function Jb(a,b){var e=a.source||{},d=a.color,f=e.color,g=b("eventColor"),l=a.backgroundColor||d||e.backgroundColor||f||b("eventBackgroundColor")||g;d=a.borderColor||d||e.borderColor||f||b("eventBorderColor")||g;a=a.textColor||e.textColor||b("eventTextColor");b=[];l&&b.push("background-color:"+l);d&&b.push("border-color:"+d);a&&b.push("color:"+a);return b.join(";")}function $a(a,b,e){if(m.isFunction(a))a=
|
||||
[a];if(a){var d,f;for(d=0;d<a.length;d++)f=a[d].apply(b,e)||f;return f}}function Ta(){for(var a=0;a<arguments.length;a++)if(arguments[a]!==ma)return arguments[a]}function mc(a,b){function e(j,t){if(t){hb(j,t);j.setDate(1)}j=N(j,true);j.setDate(1);t=hb(N(j),1);var y=N(j),S=N(t),Q=f("firstDay"),q=f("weekends")?0:1;if(q){Fa(y);Fa(S,-1,true)}ba(y,-((y.getDay()-Math.max(Q,q)+7)%7));ba(S,(7-S.getDay()+Math.max(Q,q))%7);Q=Math.round((S-y)/(Ab*7));if(f("weekMode")=="fixed"){ba(S,(6-Q)*7);Q=6}d.title=l(j,
|
||||
f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(6,Q,q?5:7,true)}var d=this;d.render=e;sb.call(d,a,b,"month");var f=d.opt,g=d.renderBasic,l=b.formatDate}function nc(a,b){function e(j,t){t&&ba(j,t*7);j=ba(N(j),-((j.getDay()-f("firstDay")+7)%7));t=ba(N(j),7);var y=N(j),S=N(t),Q=f("weekends");if(!Q){Fa(y);Fa(S,-1,true)}d.title=l(y,ba(N(S),-1),f("titleFormat"));d.start=j;d.end=t;d.visStart=y;d.visEnd=S;g(1,1,Q?7:5,false)}var d=this;d.render=e;sb.call(d,a,b,"basicWeek");var f=d.opt,g=d.renderBasic,
|
||||
@@ -106,7 +106,7 @@ t,y=-1,S=-1;for(t=0;t<l;t++)if(g>=e[t][0]&&g<e[t][1]){y=t;break}for(t=0;t<j;t++)
|
||||
g=l=null;a.build();b(t);d=y||"mousemove";m(document).bind(d,b)};e.stop=function(){m(document).unbind(d,b);return l}}function xc(a){if(a.pageX===ma){a.pageX=a.originalEvent.pageX;a.pageY=a.originalEvent.pageY}}function Pb(a){function b(l){return d[l]=d[l]||a(l)}var e=this,d={},f={},g={};e.left=function(l){return f[l]=f[l]===ma?b(l).position().left:f[l]};e.right=function(l){return g[l]=g[l]===ma?e.left(l)+b(l).width():g[l]};e.clear=function(){d={};f={};g={}}}var Ya={defaultView:"month",aspectRatio:1.35,
|
||||
header:{left:"title",center:"",right:"today prev,next"},weekends:true,allDayDefault:true,ignoreTimezone:true,lazyFetching:true,startParam:"start",endParam:"end",titleFormat:{month:"MMMM yyyy",week:"MMM d[ yyyy]{ '—'[ MMM] d yyyy}",day:"dddd, MMM d, yyyy"},columnFormat:{month:"ddd",week:"ddd M/d",day:"dddd M/d"},timeFormat:{"":"h(:mm)t"},isRTL:false,firstDay:0,monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan",
|
||||
"Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],buttonText:{prev:" ◄ ",next:" ► ",prevYear:" << ",nextYear:" >> ",today:"today",month:"month",week:"week",day:"day"},theme:false,buttonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e"},unselectAuto:true,dropAccept:"*"},yc=
|
||||
{header:{left:"next,prev today",center:"",right:"title"},buttonText:{prev:" ► ",next:" ◄ ",prevYear:" >> ",nextYear:" << "},buttonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w"}},Aa=m.fullCalendar={version:"1.5.3"},Ja=Aa.views={};m.fn.fullCalendar=function(a){if(typeof a=="string"){var b=Array.prototype.slice.call(arguments,1),e;this.each(function(){var f=m.data(this,"fullCalendar");if(f&&m.isFunction(f[a])){f=f[a].apply(f,
|
||||
{header:{left:"next,prev today",center:"",right:"title"},buttonText:{prev:" ► ",next:" ◄ ",prevYear:" >> ",nextYear:" << "},buttonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w"}},Aa=m.fullCalendar={version:"1.5.4"},Ja=Aa.views={};m.fn.fullCalendar=function(a){if(typeof a=="string"){var b=Array.prototype.slice.call(arguments,1),e;this.each(function(){var f=m.data(this,"fullCalendar");if(f&&m.isFunction(f[a])){f=f[a].apply(f,
|
||||
b);if(e===ma)e=f;a=="destroy"&&m.removeData(this,"fullCalendar")}});if(e!==ma)return e;return this}var d=a.eventSources||[];delete a.eventSources;if(a.events){d.push(a.events);delete a.events}a=m.extend(true,{},Ya,a.isRTL||a.isRTL===ma&&Ya.isRTL?yc:{},a);this.each(function(f,g){f=m(g);g=new Yb(f,a,d);f.data("fullCalendar",g);g.render()});return this};Aa.sourceNormalizers=[];Aa.sourceFetchers=[];var ac={dataType:"json",cache:false},bc=1;Aa.addDays=ba;Aa.cloneDate=N;Aa.parseDate=kb;Aa.parseISO8601=
|
||||
Bb;Aa.parseTime=mb;Aa.formatDate=Oa;Aa.formatDates=ib;var lc=["sun","mon","tue","wed","thu","fri","sat"],Ab=864E5,cc=36E5,wc=6E4,dc={s:function(a){return a.getSeconds()},ss:function(a){return Pa(a.getSeconds())},m:function(a){return a.getMinutes()},mm:function(a){return Pa(a.getMinutes())},h:function(a){return a.getHours()%12||12},hh:function(a){return Pa(a.getHours()%12||12)},H:function(a){return a.getHours()},HH:function(a){return Pa(a.getHours())},d:function(a){return a.getDate()},dd:function(a){return Pa(a.getDate())},
|
||||
ddd:function(a,b){return b.dayNamesShort[a.getDay()]},dddd:function(a,b){return b.dayNames[a.getDay()]},M:function(a){return a.getMonth()+1},MM:function(a){return Pa(a.getMonth()+1)},MMM:function(a,b){return b.monthNamesShort[a.getMonth()]},MMMM:function(a,b){return b.monthNames[a.getMonth()]},yy:function(a){return(a.getFullYear()+"").substring(2)},yyyy:function(a){return a.getFullYear()},t:function(a){return a.getHours()<12?"a":"p"},tt:function(a){return a.getHours()<12?"am":"pm"},T:function(a){return a.getHours()<
|
||||
|
||||
Vendored
+2
-2
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* FullCalendar v1.5.3 Google Calendar Plugin
|
||||
* FullCalendar v1.5.4 Google Calendar Plugin
|
||||
*
|
||||
* Copyright (c) 2011 Adam Shaw
|
||||
* Dual licensed under the MIT and GPL licenses, located in
|
||||
* MIT-LICENSE.txt and GPL-LICENSE.txt respectively.
|
||||
*
|
||||
* Date: Mon Feb 6 22:40:40 2012 -0800
|
||||
* Date: Tue Sep 4 23:38:33 2012 -0700
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -2000,7 +2000,7 @@ class CF_Object
|
||||
// }
|
||||
|
||||
//use OC's mimetype detection for files
|
||||
if(is_file($handle)){
|
||||
if(@is_file($handle)){
|
||||
$this->content_type=OC_Helper::getMimeType($handle);
|
||||
}else{
|
||||
$this->content_type=OC_Helper::getStringMimeType($handle);
|
||||
@@ -2537,7 +2537,7 @@ class CF_Object
|
||||
}
|
||||
$md5 = hash_final($ctx, false);
|
||||
rewind($data);
|
||||
} elseif ((string)is_file($data)) {
|
||||
} elseif ((string)@is_file($data)) {
|
||||
$md5 = md5_file($data);
|
||||
} else {
|
||||
$md5 = md5($data);
|
||||
|
||||
Vendored
+24
@@ -112,6 +112,10 @@ class smb {
|
||||
}
|
||||
$port = ($purl['port'] <> 139 ? ' -p ' . escapeshellarg ($purl['port']) : '');
|
||||
$options = '-O ' . escapeshellarg(SMB4PHP_SMBOPTIONS);
|
||||
|
||||
// this put env is necessary to read the output of smbclient correctly
|
||||
$old_locale = getenv('LC_ALL');
|
||||
putenv('LC_ALL=en_US.UTF-8');
|
||||
$output = popen (SMB4PHP_SMBCLIENT." -N {$auth} {$options} {$port} {$options} {$params} 2>/dev/null", 'r');
|
||||
$info = array ();
|
||||
$info['info']= array ();
|
||||
@@ -180,6 +184,14 @@ class smb {
|
||||
}
|
||||
}
|
||||
pclose($output);
|
||||
|
||||
// restore previous locale
|
||||
if ($old_locale===false) {
|
||||
putenv('LC_ALL');
|
||||
} else {
|
||||
putenv('LC_ALL='.$old_locale);
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
@@ -229,6 +241,8 @@ class smb {
|
||||
}
|
||||
|
||||
function addstatcache ($url, $info) {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
$is_file = (strpos ($info['attr'],'D') === FALSE);
|
||||
$s = ($is_file) ? stat ('/etc/passwd') : stat ('/tmp');
|
||||
@@ -238,11 +252,15 @@ class smb {
|
||||
}
|
||||
|
||||
function getstatcache ($url) {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
return isset ($__smb_cache['stat'][$url]) ? $__smb_cache['stat'][$url] : FALSE;
|
||||
}
|
||||
|
||||
function clearstatcache ($url='') {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
if ($url == '') $__smb_cache['stat'] = array (); else unset ($__smb_cache['stat'][$url]);
|
||||
}
|
||||
@@ -358,16 +376,22 @@ class smb_stream_wrapper extends smb {
|
||||
# cache
|
||||
|
||||
function adddircache ($url, $content) {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
return $__smb_cache['dir'][$url] = $content;
|
||||
}
|
||||
|
||||
function getdircache ($url) {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
return isset ($__smb_cache['dir'][$url]) ? $__smb_cache['dir'][$url] : FALSE;
|
||||
}
|
||||
|
||||
function cleardircache ($url='') {
|
||||
$url = str_replace('//', '/', $url);
|
||||
$url = rtrim($url, '/');
|
||||
global $__smb_cache;
|
||||
if ($url == ''){
|
||||
$__smb_cache['dir'] = array ();
|
||||
|
||||
@@ -32,7 +32,7 @@ $htaccessWorking=(getenv('htaccessWorking')=='true');
|
||||
$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize'));
|
||||
$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size'));
|
||||
$maxUploadFilesize = OCP\Util::humanFileSize(min($upload_max_filesize, $post_max_size));
|
||||
if($_POST) {
|
||||
if($_POST && OC_Util::isCallRegistered()) {
|
||||
if(isset($_POST['maxUploadSize'])) {
|
||||
if(($setMaxSize = OC_Files::setUploadLimit(OCP\Util::computerFileSize($_POST['maxUploadSize']))) !== false) {
|
||||
$maxUploadFilesize = OCP\Util::humanFileSize($setMaxSize);
|
||||
|
||||
@@ -10,7 +10,7 @@ OCP\JSON::callCheck();
|
||||
$dir = stripslashes($_POST["dir"]);
|
||||
$files = isset($_POST["file"]) ? stripslashes($_POST["file"]) : stripslashes($_POST["files"]);
|
||||
|
||||
$files = explode(';', $files);
|
||||
$files = json_decode($files);
|
||||
$filesWithError = '';
|
||||
$success = true;
|
||||
//Now delete
|
||||
|
||||
@@ -33,4 +33,9 @@ OCP\User::checkLoggedIn();
|
||||
$files = $_GET["files"];
|
||||
$dir = $_GET["dir"];
|
||||
|
||||
if ($files == "Shared" and $dir == "/") {
|
||||
$files = '';
|
||||
$dir = "/Shared";
|
||||
}
|
||||
|
||||
OC_Files::get($dir, $files, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
|
||||
@@ -9,7 +9,7 @@ OCP\JSON::callCheck();
|
||||
// Get data
|
||||
$dir = stripslashes($_GET["dir"]);
|
||||
$file = stripslashes($_GET["file"]);
|
||||
$target = stripslashes($_GET["target"]);
|
||||
$target = stripslashes(urldecode($_GET["target"]));
|
||||
|
||||
|
||||
if(OC_Files::move($dir, $file, $target, $file)) {
|
||||
|
||||
@@ -65,6 +65,7 @@ if($source) {
|
||||
$target=$dir.'/'.$filename;
|
||||
$result=OC_Filesystem::file_put_contents($target, $sourceStream);
|
||||
if($result) {
|
||||
$target = OC_Filesystem::normalizePath($target);
|
||||
$meta = OC_FileCache::get($target);
|
||||
$mime=$meta['mimetype'];
|
||||
$id = OC_FileCache::getId($target);
|
||||
|
||||
@@ -48,10 +48,12 @@ if(strpos($dir, '..') === false) {
|
||||
$fileCount=count($files['name']);
|
||||
for($i=0;$i<$fileCount;$i++) {
|
||||
$target = OCP\Files::buildNotExistingFileName(stripslashes($dir), $files['name'][$i]);
|
||||
// $path needs to be normalized - this failed within drag'n'drop upload to a sub-folder
|
||||
$target = OC_Filesystem::normalizePath($target);
|
||||
if(is_uploaded_file($files['tmp_name'][$i]) and OC_Filesystem::fromTmpFile($files['tmp_name'][$i], $target)) {
|
||||
$meta = OC_FileCache::get($target);
|
||||
$id = OC_FileCache::getId($target);
|
||||
$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'],'size'=>$meta['size'], 'id'=>$id, 'name'=>basename($target));
|
||||
$result[]=array( "status" => "success", 'mime'=>$meta['mimetype'], 'size'=>$meta['size'], 'id'=>$id, 'name'=>basename($target));
|
||||
}
|
||||
}
|
||||
OCP\JSON::encodedPrint($result);
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
* The final URL will look like http://.../remote.php/filesync/oc_chunked/path/to/file
|
||||
*/
|
||||
|
||||
// only need filesystem apps
|
||||
$RUNTIME_APPTYPES=array('filesystem','authentication');
|
||||
// load needed apps
|
||||
$RUNTIME_APPTYPES=array('filesystem','authentication','logging');
|
||||
OC_App::loadApps($RUNTIME_APPTYPES);
|
||||
if(!OC_User::isLoggedIn()) {
|
||||
if(!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
// only need filesystem apps
|
||||
$RUNTIME_APPTYPES=array('filesystem','authentication');
|
||||
// load needed apps
|
||||
$RUNTIME_APPTYPES=array('filesystem','authentication','logging');
|
||||
OC_App::loadApps($RUNTIME_APPTYPES);
|
||||
|
||||
OC_Util::obEnd();
|
||||
|
||||
// Backends
|
||||
$authBackend = new OC_Connector_Sabre_Auth();
|
||||
$lockBackend = new OC_Connector_Sabre_Locks();
|
||||
@@ -41,6 +43,7 @@ $server->setBaseUri($baseuri);
|
||||
$server->addPlugin(new Sabre_DAV_Auth_Plugin($authBackend,'ownCloud'));
|
||||
$server->addPlugin(new Sabre_DAV_Locks_Plugin($lockBackend));
|
||||
$server->addPlugin(new Sabre_DAV_Browser_Plugin(false)); // Show something in the Browser, but no upload
|
||||
$server->addPlugin(new OC_Connector_Sabre_QuotaPlugin());
|
||||
|
||||
// And off we go!
|
||||
$server->exec();
|
||||
|
||||
@@ -5,10 +5,10 @@ $installedVersion=OCP\Config::getAppValue('files', 'installed_version');
|
||||
if (version_compare($installedVersion, '1.1.6', '<')) {
|
||||
$query = OC_DB::prepare( "SELECT `propertyname`, `propertypath`, `userid` FROM `*PREFIX*properties`" );
|
||||
$result = $query->execute();
|
||||
$updateQuery = OC_DB::prepare('UPDATE `*PREFIX*properties` SET `propertyname` = ? WHERE `userid` = ? AND `propertypath` = ?');
|
||||
while( $row = $result->fetchRow()){
|
||||
if ( $row["propertyname"][0] != '{' ) {
|
||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyname` = ? WHERE `userid` = ? AND `propertypath` = ?' );
|
||||
$query->execute( array( '{DAV:}' + $row["propertyname"], $row["userid"], $row["propertypath"] ));
|
||||
$updateQuery->execute(array('{DAV:}' + $row["propertyname"], $row["userid"], $row["propertypath"]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ table th#headerDate, table td.date { width:11em; padding:0 .1em 0 1em; text-alig
|
||||
table td.selection, table th.selection, table td.fileaction { width:2em; text-align:center; }
|
||||
table td.filename a.name { display:block; height:1.5em; vertical-align:middle; margin-left:3em; }
|
||||
table tr[data-type="dir"] td.filename a.name span.nametext {font-weight:bold; }
|
||||
table td.filename a.name input, table td.filename a.name form { width:100%; cursor:text; }
|
||||
table td.filename input.filename { width:100%; cursor:text; }
|
||||
table td.filename a, table td.login, table td.logout, table td.download, table td.upload, table td.create, table td.delete { padding:.2em .5em .5em 0; }
|
||||
table td.filename .nametext, .uploadtext, .modified { float:left; padding:.3em 0; }
|
||||
// TODO fix usability bug (accidental file/folder selection)
|
||||
table td.filename .nametext { width:40em; overflow:hidden; text-overflow:ellipsis; }
|
||||
table td.filename .uploadtext { font-weight:normal; margin-left:.5em; }
|
||||
table td.filename form { float:left; font-size:.85em; }
|
||||
table td.filename form { font-size:.85em; margin-left:3em; margin-right:3em; }
|
||||
table thead.fixed tr{ position:fixed; top:6.5em; z-index:49; -moz-box-shadow:0 -3px 7px #ddd; -webkit-box-shadow:0 -3px 7px #ddd; box-shadow:0 -3px 7px #ddd; }
|
||||
table thead.fixed { height:2em; }
|
||||
#fileList tr td.filename>input[type=checkbox]:first-child { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; float:left; margin:.7em 0 0 1em; /* bigger clickable area doesn’t work in FF width:2.8em; height:2.4em;*/ -webkit-transition:opacity 200ms; -moz-transition:opacity 200ms; -o-transition:opacity 200ms; transition:opacity 200ms; }
|
||||
|
||||
@@ -44,5 +44,5 @@ header('Content-Disposition: attachment; filename="'.basename($filename).'"');
|
||||
OCP\Response::disableCaching();
|
||||
header('Content-Length: '.OC_Filesystem::filesize($filename));
|
||||
|
||||
@ob_end_clean();
|
||||
OC_Util::obEnd();
|
||||
OC_Filesystem::readfile( $filename );
|
||||
|
||||
@@ -36,7 +36,7 @@ if(!isset($_SESSION['timezone'])) {
|
||||
}
|
||||
OCP\App::setActiveNavigationEntry( 'files_index' );
|
||||
// Load the files
|
||||
$dir = isset( $_GET['dir'] ) ? stripslashes($_GET['dir']) : '';
|
||||
$dir = isset( $_GET['dir'] ) ? urldecode(stripslashes($_GET['dir'])) : '';
|
||||
// Redirect if directory does not exist
|
||||
if(!OC_Filesystem::is_dir($dir.'/')) {
|
||||
header('Location: '.$_SERVER['SCRIPT_NAME'].'');
|
||||
|
||||
+24
-16
@@ -15,9 +15,9 @@ var FileList={
|
||||
extension=false;
|
||||
}
|
||||
html+='<td class="filename" style="background-image:url('+img+')"><input type="checkbox" />';
|
||||
html+='<a class="name" href="download.php?file='+$('#dir').val().replace(/</, '<').replace(/>/, '>')+'/'+name+'"><span class="nametext">'+basename;
|
||||
html+='<a class="name" href="download.php?file='+$('#dir').val().replace(/</, '<').replace(/>/, '>')+'/'+escapeHTML(name)+'"><span class="nametext">'+escapeHTML(basename);
|
||||
if(extension){
|
||||
html+='<span class="extension">'+extension+'</span>';
|
||||
html+='<span class="extension">'+escapeHTML(extension)+'</span>';
|
||||
}
|
||||
html+='</span></a></td>';
|
||||
if(size!='Pending'){
|
||||
@@ -137,16 +137,19 @@ var FileList={
|
||||
tr=$('tr').filterAttr('data-file',name);
|
||||
tr.data('renaming',true);
|
||||
td=tr.children('td.filename');
|
||||
input=$('<input class="filename"></input>').val(name);
|
||||
input=$('<input class="filename"/>').val(name);
|
||||
form=$('<form></form>');
|
||||
form.append(input);
|
||||
td.children('a.name').text('');
|
||||
td.children('a.name').append(form);
|
||||
td.children('a.name').hide();
|
||||
td.append(form);
|
||||
input.focus();
|
||||
form.submit(function(event){
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
var newname=input.val();
|
||||
if (Files.containsInvalidCharacters(newname)) {
|
||||
return false;
|
||||
}
|
||||
if (newname != name) {
|
||||
if (FileList.checkName(name, newname, false)) {
|
||||
newname = name;
|
||||
@@ -156,11 +159,11 @@ var FileList={
|
||||
OC.dialogs.alert(result.data.message, 'Error moving file');
|
||||
newname = name;
|
||||
}
|
||||
tr.data('renaming',false);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
tr.data('renaming',false);
|
||||
tr.attr('data-file', newname);
|
||||
var path = td.children('a.name').attr('href');
|
||||
td.children('a.name').attr('href', path.replace(encodeURIComponent(name), encodeURIComponent(newname)));
|
||||
@@ -169,13 +172,15 @@ var FileList={
|
||||
} else {
|
||||
var basename=newname;
|
||||
}
|
||||
td.children('a.name').empty();
|
||||
var span=$('<span class="nametext"></span>');
|
||||
span.text(basename);
|
||||
td.children('a.name').append(span);
|
||||
td.find('a.name span.nametext').text(basename);
|
||||
if (newname.indexOf('.') > 0 && tr.data('type') != 'dir') {
|
||||
span.append($('<span class="extension">'+newname.substr(newname.lastIndexOf('.'))+'</span>'));
|
||||
if (td.find('a.name span.extension').length == 0 ) {
|
||||
td.find('a.name span.nametext').append('<span class="extension"></span>');
|
||||
}
|
||||
td.find('a.name span.extension').text(newname.substr(newname.lastIndexOf('.')));
|
||||
}
|
||||
form.remove();
|
||||
td.children('a.name').show();
|
||||
return false;
|
||||
});
|
||||
input.click(function(event){
|
||||
@@ -189,9 +194,9 @@ var FileList={
|
||||
checkName:function(oldName, newName, isNewFile) {
|
||||
if (isNewFile || $('tr').filterAttr('data-file', newName).length > 0) {
|
||||
if (isNewFile) {
|
||||
$('#notification').html(newName+' '+t('files', 'already exists')+'<span class="replace">'+t('files', 'replace')+'</span><span class="suggest">'+t('files', 'suggest name')+'</span><span class="cancel">'+t('files', 'cancel')+'</span>');
|
||||
$('#notification').html(escapeHTML(newName)+' '+t('files', 'already exists')+'<span class="replace">'+t('files', 'replace')+'</span><span class="suggest">'+t('files', 'suggest name')+'</span><span class="cancel">'+t('files', 'cancel')+'</span>');
|
||||
} else {
|
||||
$('#notification').html(newName+' '+t('files', 'already exists')+'<span class="replace">'+t('files', 'replace')+'</span><span class="cancel">'+t('files', 'cancel')+'</span>');
|
||||
$('#notification').html(escapeHTML(newName)+' '+t('files', 'already exists')+'<span class="replace">'+t('files', 'replace')+'</span><span class="cancel">'+t('files', 'cancel')+'</span>');
|
||||
}
|
||||
$('#notification').data('oldName', oldName);
|
||||
$('#notification').data('newName', newName);
|
||||
@@ -272,16 +277,16 @@ var FileList={
|
||||
} else {
|
||||
// NOTE: Temporary fix to change the text to unshared for files in root of Shared folder
|
||||
if ($('#dir').val() == '/Shared') {
|
||||
$('#notification').html(t('files', 'unshared')+' '+files+'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
$('#notification').html(t('files', 'unshared')+' '+ escapeHTML(files) +'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
} else {
|
||||
$('#notification').html(t('files', 'deleted')+' '+files+'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
$('#notification').html(t('files', 'deleted')+' '+ escapeHTML(files)+'<span class="undo">'+t('files', 'undo')+'</span>');
|
||||
}
|
||||
$('#notification').fadeIn();
|
||||
}
|
||||
},
|
||||
finishDelete:function(ready,sync){
|
||||
if(!FileList.deleteCanceled && FileList.deleteFiles){
|
||||
var fileNames=FileList.deleteFiles.join(';');
|
||||
var fileNames=JSON.stringify(FileList.deleteFiles);
|
||||
$.ajax({
|
||||
url: OC.filePath('files', 'ajax', 'delete.php'),
|
||||
async:!sync,
|
||||
@@ -373,4 +378,7 @@ $(document).ready(function(){
|
||||
FileList.lastAction();
|
||||
}
|
||||
});
|
||||
$(window).unload(function (){
|
||||
$(window).trigger('beforeunload');
|
||||
});
|
||||
});
|
||||
|
||||
+40
-12
@@ -25,6 +25,18 @@ Files={
|
||||
delete uploadingFiles[index];
|
||||
});
|
||||
procesSelection();
|
||||
},
|
||||
containsInvalidCharacters:function (name) {
|
||||
var invalid_characters = ['\\', '/', '<', '>', ':', '"', '|', '?', '*'];
|
||||
for (var i = 0; i < invalid_characters.length; i++) {
|
||||
if (name.indexOf(invalid_characters[i]) != -1) {
|
||||
$('#notification').text(t('files', "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed."));
|
||||
$('#notification').fadeIn();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$('#notification').fadeOut();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
$(document).ready(function() {
|
||||
@@ -199,7 +211,7 @@ $(document).ready(function() {
|
||||
$(document).bind('drop dragover', function (e) {
|
||||
e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone
|
||||
});
|
||||
|
||||
|
||||
if ( document.getElementById("data-upload-form") ) {
|
||||
$(function() {
|
||||
$('.file_upload_start').fileupload({
|
||||
@@ -233,7 +245,12 @@ $(document).ready(function() {
|
||||
}
|
||||
});
|
||||
}else{
|
||||
var date=new Date();
|
||||
var dropTarget = $(e.originalEvent.target).closest('tr');
|
||||
if(dropTarget && dropTarget.attr('data-type') === 'dir') { // drag&drop upload to folder
|
||||
var dirName = dropTarget.attr('data-file')
|
||||
}
|
||||
|
||||
var date=new Date();
|
||||
if(files){
|
||||
for(var i=0;i<files.length;i++){
|
||||
if(files[i].size>0){
|
||||
@@ -286,7 +303,10 @@ $(document).ready(function() {
|
||||
var jqXHR = $('.file_upload_start').fileupload('send', {files: files[i],
|
||||
formData: function(form) {
|
||||
var formArray = form.serializeArray();
|
||||
formArray[1]['value'] = dirName;
|
||||
// array index 0 contains the max files size
|
||||
// array index 1 contains the request token
|
||||
// array index 2 contains the directory
|
||||
formArray[2]['value'] = dirName;
|
||||
return formArray;
|
||||
}}).success(function(result, textStatus, jqXHR) {
|
||||
var response;
|
||||
@@ -296,7 +316,13 @@ $(document).ready(function() {
|
||||
$('#notification').fadeIn();
|
||||
}
|
||||
var file=response[0];
|
||||
// TODO: this doesn't work if the file name has been changed server side
|
||||
delete uploadingFiles[dirName][file.name];
|
||||
if ($.assocArraySize(uploadingFiles[dirName]) == 0) {
|
||||
delete uploadingFiles[dirName];
|
||||
}
|
||||
|
||||
var uploadtext = $('tr').filterAttr('data-type', 'dir').filterAttr('data-file', dirName).find('.uploadtext')
|
||||
var currentUploads = parseInt(uploadtext.attr('currentUploads'));
|
||||
currentUploads -= 1;
|
||||
uploadtext.attr('currentUploads', currentUploads);
|
||||
@@ -496,12 +522,14 @@ $(document).ready(function() {
|
||||
$(this).append(input);
|
||||
input.focus();
|
||||
input.change(function(){
|
||||
if(type != 'web' && $(this).val().indexOf('/')!=-1){
|
||||
$('#notification').text(t('files','Invalid name, \'/\' is not allowed.'));
|
||||
$('#notification').fadeIn();
|
||||
return;
|
||||
}
|
||||
var name = getUniqueName($(this).val());
|
||||
if (type != 'web' && Files.containsInvalidCharacters($(this).val())) {
|
||||
return;
|
||||
} else if( type == 'folder' && $('#dir').val() == '/' && $(this).val() == 'Shared') {
|
||||
$('#notification').text(t('files','Invalid folder name. Usage of "Shared" is reserved by Owncloud'));
|
||||
$('#notification').fadeIn();
|
||||
return;
|
||||
}
|
||||
var name = getUniqueName($(this).val());
|
||||
if (name != $(this).val()) {
|
||||
FileList.checkName(name, $(this).val(), true);
|
||||
var hidden = true;
|
||||
@@ -707,7 +735,7 @@ function updateBreadcrumb(breadcrumbHtml) {
|
||||
|
||||
//options for file drag/dropp
|
||||
var dragOptions={
|
||||
distance: 20, revert: 'invalid', opacity: 0.7,
|
||||
distance: 20, revert: 'invalid', opacity: 0.7, helper: 'clone',
|
||||
stop: function(event, ui) {
|
||||
$('#fileList tr td.filename').addClass('ui-draggable');
|
||||
}
|
||||
@@ -826,7 +854,7 @@ function getSelectedFiles(property){
|
||||
name:$(element).attr('data-file'),
|
||||
mime:$(element).data('mime'),
|
||||
type:$(element).data('type'),
|
||||
size:$(element).data('size'),
|
||||
size:$(element).data('size')
|
||||
};
|
||||
if(property){
|
||||
files.push(file[property]);
|
||||
@@ -863,7 +891,7 @@ function getMimeIcon(mime, ready){
|
||||
if(getMimeIcon.cache[mime]){
|
||||
ready(getMimeIcon.cache[mime]);
|
||||
}else{
|
||||
$.get( OC.filePath('files','ajax','mimeicon.php')+'?mime='+mime, function(path){
|
||||
$.get( OC.filePath('files','ajax','mimeicon.php'), {mime: mime}, function(path){
|
||||
getMimeIcon.cache[mime]=path;
|
||||
ready(getMimeIcon.cache[mime]);
|
||||
});
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"folders" => "Ordner",
|
||||
"file" => "Datei",
|
||||
"files" => "Dateien",
|
||||
"seconds ago" => "Sekunden her",
|
||||
"seconds ago" => "Gerade eben",
|
||||
"minute ago" => "Minute her",
|
||||
"minutes ago" => "Minuten her",
|
||||
"today" => "Heute",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<input name="maxZipInputSize" id="maxZipInputSize" style="width:180px;" value='<?php echo $_['maxZipInputSize'] ?>' title="<?php echo $l->t( '0 is unlimited' ); ?>"<?php if (!$_['allowZipDownload']) echo ' disabled="disabled"'; ?> />
|
||||
<label for="maxZipInputSize"><?php echo $l->t( 'Maximum input size for ZIP files' ); ?> </label><br />
|
||||
|
||||
<input type="hidden" value="<?php echo $_['requesttoken']; ?>" name="requesttoken" />
|
||||
<input type="submit" name="submitFilesAdminSettings" id="submitFilesAdminSettings" value="<?php echo $l->t( 'Save' ); ?>"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
<div class="file_upload_wrapper svg">
|
||||
<form data-upload-id='1' id="data-upload-form" class="file_upload_form" action="<?php echo OCP\Util::linkTo('files', 'ajax/upload.php'); ?>" method="post" enctype="multipart/form-data" target="file_upload_target_1">
|
||||
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $_['uploadMaxFilesize'] ?>" id="max_upload">
|
||||
<!-- Send the requesttoken, this is needed for older IE versions because they don't send the CSRF token via HTTP header in this case -->
|
||||
<input type="hidden" name="requesttoken" value="<?php echo $_['requesttoken'] ?>" id="requesttoken">
|
||||
<input type="hidden" class="max_human_file_size" value="(max <?php echo $_['uploadMaxHumanFilesize']; ?>)">
|
||||
<input type="hidden" name="dir" value="<?php echo $_['dir'] ?>" id="dir">
|
||||
<input class="file_upload_start" type="file" name='files[]'/>
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
<script type="text/javascript">
|
||||
<?php if ( array_key_exists('publicListView', $_) && $_['publicListView'] == true ) {
|
||||
echo "var publicListView = true;";
|
||||
} else {
|
||||
echo "var publicListView = false;";
|
||||
}
|
||||
?>
|
||||
</script>
|
||||
|
||||
<?php foreach($_['files'] as $file):
|
||||
$simple_file_size = OCP\simple_file_size($file['size']);
|
||||
$simple_size_color = intval(200-$file['size']/(1024*1024)*2); // the bigger the file, the darker the shade of grey; megabytes*2
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
OC_Util::checkAdminUser();
|
||||
|
||||
$tmpl = new OCP\Template( 'files_encryption', 'settings');
|
||||
$blackList=explode(',',OCP\Config::getAppValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg'));
|
||||
$enabled=(OCP\Config::getAppValue('files_encryption','enable_encryption','true')=='true');
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
OCP\JSON::checkAppEnabled('files_external');
|
||||
OCP\JSON::callCheck();
|
||||
|
||||
if (!isset($_POST['isPersonal']))
|
||||
return;
|
||||
if (!isset($_POST['mountPoint']))
|
||||
return;
|
||||
if (!isset($_POST['mountType']))
|
||||
return;
|
||||
if (!isset($_POST['applicable']))
|
||||
return;
|
||||
|
||||
if ($_POST['isPersonal'] == 'true') {
|
||||
OCP\JSON::checkLoggedIn();
|
||||
$isPersonal = true;
|
||||
@@ -10,4 +19,5 @@ if ($_POST['isPersonal'] == 'true') {
|
||||
OCP\JSON::checkAdminUser();
|
||||
$isPersonal = false;
|
||||
}
|
||||
|
||||
OC_Mount_Config::removeMountPoint($_POST['mountPoint'], $_POST['mountType'], $_POST['applicable'], $isPersonal);
|
||||
|
||||
@@ -109,10 +109,10 @@ class OC_Mount_Config {
|
||||
return $personal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add directory for mount point to the filesystem
|
||||
* @param OC_Fileview instance $view
|
||||
* @param string path to mount point
|
||||
/**
|
||||
* Add directory for mount point to the filesystem
|
||||
* @param OC_Fileview instance $view
|
||||
* @param string path to mount point
|
||||
*/
|
||||
private static function addMountPointDirectory($view, $path) {
|
||||
$dir = '';
|
||||
@@ -285,9 +285,17 @@ class OC_Mount_Config {
|
||||
public static function getCertificates() {
|
||||
$view = \OCP\Files::getStorage('files_external');
|
||||
$path=\OCP\Config::getSystemValue('datadirectory').$view->getAbsolutePath("").'uploads/';
|
||||
if (!is_dir($path)) mkdir($path);
|
||||
\OCP\Util::writeLog('files_external', 'checking path '.$path, \OCP\Util::INFO);
|
||||
if(!is_dir($path)) {
|
||||
//path might not exist (e.g. non-standard OC_User::getHome() value)
|
||||
//in this case create full path using 3rd (recursive=true) parameter.
|
||||
mkdir($path, 0777, true);
|
||||
}
|
||||
$result = array();
|
||||
$handle = opendir($path);
|
||||
if (!$handle) {
|
||||
return array();
|
||||
}
|
||||
while (false !== ($file = readdir($handle))) {
|
||||
if($file != '.' && $file != '..') $result[] = $file;
|
||||
}
|
||||
@@ -319,4 +327,39 @@ class OC_Mount_Config {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if smbclient is installed
|
||||
*/
|
||||
public static function checksmbclient() {
|
||||
if(function_exists('shell_exec')) {
|
||||
$output=shell_exec('which smbclient');
|
||||
return (empty($output)?false:true);
|
||||
}else{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if php-ftp is installed
|
||||
*/
|
||||
public static function checkphpftp() {
|
||||
if(function_exists('ftp_login')) {
|
||||
return(true);
|
||||
}else{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check dependencies
|
||||
*/
|
||||
public static function checkDependencies() {
|
||||
$l= new OC_L10N('files_external');
|
||||
$txt='';
|
||||
if(!OC_Mount_Config::checksmbclient()) $txt.=$l->t('<b>Warning:</b> "smbclient" is not installed. Mounting of CIFS/SMB shares is not possible. Please ask your system administrator to install it.').'<br />';
|
||||
if(!OC_Mount_Config::checkphpftp()) $txt.=$l->t('<b>Warning:</b> The FTP support in PHP is not enabled or installed. Mounting of FTP shares is not possible. Please ask your system administrator to install it.').'<br />';
|
||||
|
||||
return($txt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,15 @@ class OC_FileStorage_FTP extends OC_FileStorage_StreamWrapper{
|
||||
$this->host=$params['host'];
|
||||
$this->user=$params['user'];
|
||||
$this->password=$params['password'];
|
||||
$this->secure=isset($params['secure'])?(bool)$params['secure']:false;
|
||||
if(isset($params['secure'])){
|
||||
if(is_string($params['secure'])){
|
||||
$this->secure = ($params['secure'] === 'true');
|
||||
}else{
|
||||
$this->secure = (bool)$params['secure'];
|
||||
}
|
||||
}else{
|
||||
$this->secure = false;
|
||||
}
|
||||
$this->root=isset($params['root'])?$params['root']:'/';
|
||||
if(!$this->root || $this->root[0]!='/') {
|
||||
$this->root='/'.$this->root;
|
||||
|
||||
@@ -58,10 +58,6 @@ class OC_FileStorage_SMB extends OC_FileStorage_StreamWrapper{
|
||||
}
|
||||
}
|
||||
|
||||
public function filetype($path) {
|
||||
return (bool)@$this->opendir($path);//using opendir causes the same amount of requests and caches the content of the folder in one go
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a file or folder has been updated since $time
|
||||
* @param int $time
|
||||
|
||||
@@ -39,7 +39,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
* @return string
|
||||
*/
|
||||
private function getContainerName($path) {
|
||||
$path=trim($this->root.$path,'/');
|
||||
$path=trim(trim($this->root,'/')."/".$path,'/.');
|
||||
return str_replace('/','\\',$path);
|
||||
}
|
||||
|
||||
@@ -70,11 +70,11 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
* @return CF_Container
|
||||
*/
|
||||
private function createContainer($path) {
|
||||
if($path=='' or $path=='/') {
|
||||
if($path=='' or $path=='/' or $path=='.') {
|
||||
return $this->conn->create_container($this->getContainerName($path));
|
||||
}
|
||||
$parent=dirname($path);
|
||||
if($parent=='' or $parent=='/') {
|
||||
if($parent=='' or $parent=='/' or $parent=='.') {
|
||||
$parentContainer=$this->rootContainer;
|
||||
}else{
|
||||
if(!$this->containerExists($parent)) {
|
||||
@@ -100,6 +100,9 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
if(is_null($container)) {
|
||||
return null;
|
||||
}else{
|
||||
if ($path=="/" or $path=='') {
|
||||
return null;
|
||||
}
|
||||
try{
|
||||
$obj=$container->get_object(basename($path));
|
||||
$this->objects[$path]=$obj;
|
||||
@@ -135,7 +138,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
private function createObject($path) {
|
||||
$container=$this->getContainer(dirname($path));
|
||||
if(!is_null($container)) {
|
||||
$container=$this->createContainer($path);
|
||||
$container=$this->createContainer(dirname($path));
|
||||
}
|
||||
return $container->create_object(basename($path));
|
||||
}
|
||||
@@ -268,7 +271,15 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
$this->host=$params['host'];
|
||||
$this->user=$params['user'];
|
||||
$this->root=isset($params['root'])?$params['root']:'/';
|
||||
$this->secure=isset($params['secure'])?(bool)$params['secure']:true;
|
||||
if(isset($params['secure'])){
|
||||
if(is_string($params['secure'])){
|
||||
$this->secure = ($params['secure'] === 'true');
|
||||
}else{
|
||||
$this->secure = (bool)$params['secure'];
|
||||
}
|
||||
}else{
|
||||
$this->secure = false;
|
||||
}
|
||||
if(!$this->root || $this->root[0]!='/') {
|
||||
$this->root='/'.$this->root;
|
||||
}
|
||||
@@ -277,7 +288,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
|
||||
$this->conn = new CF_Connection($this->auth);
|
||||
|
||||
if(!$this->containerExists($this->root)) {
|
||||
if(!$this->containerExists('/')) {
|
||||
$this->rootContainer=$this->createContainer('/');
|
||||
}else{
|
||||
$this->rootContainer=$this->getContainer('/');
|
||||
@@ -391,6 +402,9 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
}
|
||||
|
||||
public function unlink($path) {
|
||||
if($this->containerExists($path)) {
|
||||
return $this->rmdir($path);
|
||||
}
|
||||
if($this->objectExists($path)) {
|
||||
$container=$this->getContainer(dirname($path));
|
||||
$container->delete_object(basename($path));
|
||||
@@ -401,13 +415,13 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
}
|
||||
|
||||
public function fopen($path,$mode) {
|
||||
$obj=$this->getObject($path);
|
||||
if(is_null($obj)) {
|
||||
return false;
|
||||
}
|
||||
switch($mode) {
|
||||
case 'r':
|
||||
case 'rb':
|
||||
$obj=$this->getObject($path);
|
||||
if (is_null($obj)) {
|
||||
return false;
|
||||
}
|
||||
$fp = fopen('php://temp', 'r+');
|
||||
$obj->stream($fp);
|
||||
|
||||
@@ -440,7 +454,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
}
|
||||
|
||||
public function free_space($path) {
|
||||
return 0;
|
||||
return 1024*1024*1024*8;
|
||||
}
|
||||
|
||||
public function touch($path,$mtime=null) {
|
||||
@@ -481,7 +495,17 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
}
|
||||
|
||||
public function stat($path) {
|
||||
$container=$this->getContainer($path);
|
||||
if (!is_null($container)) {
|
||||
return array(
|
||||
'mtime'=>-1,
|
||||
'size'=>$container->bytes_used,
|
||||
'ctime'=>-1
|
||||
);
|
||||
}
|
||||
|
||||
$obj=$this->getObject($path);
|
||||
|
||||
if(is_null($obj)) {
|
||||
return false;
|
||||
}
|
||||
@@ -505,7 +529,7 @@ class OC_FileStorage_SWIFT extends OC_Filestorage_Common{
|
||||
$obj->save_to_filename($tmpFile);
|
||||
return $tmpFile;
|
||||
}else{
|
||||
return false;
|
||||
return OCP\Files::tmpFile();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,15 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
|
||||
$this->host=$host;
|
||||
$this->user=$params['user'];
|
||||
$this->password=$params['password'];
|
||||
$this->secure=(isset($params['secure']) && $params['secure'] == 'true')?true:false;
|
||||
if(isset($params['secure'])){
|
||||
if(is_string($params['secure'])){
|
||||
$this->secure = ($params['secure'] === 'true');
|
||||
}else{
|
||||
$this->secure = (bool)$params['secure'];
|
||||
}
|
||||
}else{
|
||||
$this->secure = false;
|
||||
}
|
||||
$this->root=isset($params['root'])?$params['root']:'/';
|
||||
if(!$this->root || $this->root[0]!='/') {
|
||||
$this->root='/'.$this->root;
|
||||
@@ -131,6 +139,9 @@ class OC_FileStorage_DAV extends OC_Filestorage_Common{
|
||||
switch($mode) {
|
||||
case 'r':
|
||||
case 'rb':
|
||||
if(!$this->file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
//straight up curl instead of sabredav here, sabredav put's the entire get result in memory
|
||||
$curl = curl_init();
|
||||
$fp = fopen('php://temp', 'r+');
|
||||
|
||||
@@ -29,5 +29,6 @@ $tmpl = new OCP\Template('files_external', 'settings');
|
||||
$tmpl->assign('isAdminPage', false, false);
|
||||
$tmpl->assign('mounts', OC_Mount_Config::getPersonalMountPoints());
|
||||
$tmpl->assign('certs', OC_Mount_Config::getCertificates());
|
||||
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies(),false);
|
||||
$tmpl->assign('backends', $backends);
|
||||
return $tmpl->fetchPage();
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
OC_Util::checkAdminUser();
|
||||
|
||||
OCP\Util::addScript('files_external', 'settings');
|
||||
OCP\Util::addscript('3rdparty', 'chosen/chosen.jquery.min');
|
||||
OCP\Util::addStyle('files_external', 'settings');
|
||||
@@ -30,5 +32,6 @@ $tmpl->assign('mounts', OC_Mount_Config::getSystemMountPoints());
|
||||
$tmpl->assign('backends', OC_Mount_Config::getBackends());
|
||||
$tmpl->assign('groups', OC_Group::getGroups());
|
||||
$tmpl->assign('users', OCP\User::getUsers());
|
||||
$tmpl->assign('dependencies', OC_Mount_Config::checkDependencies(),false);
|
||||
$tmpl->assign('allowUserMounting', OCP\Config::getAppValue('files_external', 'allow_user_mounting', 'yes'));
|
||||
return $tmpl->fetchPage();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<form id="files_external">
|
||||
<fieldset class="personalblock">
|
||||
<legend><strong><?php echo $l->t('External Storage'); ?></strong></legend>
|
||||
<?php if (isset($_['dependencies']) and ($_['dependencies']<>'')) echo($_['dependencies']); ?>
|
||||
<table id="externalStorage" data-admin='<?php echo json_encode($_['isAdminPage']); ?>'>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -60,7 +61,7 @@
|
||||
<?php if ($_['isAdminPage']): ?>
|
||||
<td class="applicable" align="right" data-applicable-groups='<?php if (isset($mount['applicable']['groups'])) echo json_encode($mount['applicable']['groups']); ?>' data-applicable-users='<?php if (isset($mount['applicable']['users'])) echo json_encode($mount['applicable']['users']); ?>'>
|
||||
<select class="chzn-select" multiple style="width:20em;" data-placeholder="<?php echo $l->t('None set'); ?>">
|
||||
<option value="all"><?php echo $l->t('All Users'); ?></option>
|
||||
<option value="all" <?php if (isset($mount['applicable']['users']) && in_array('all', $mount['applicable']['users'])) echo 'selected="selected"';?> ><?php echo $l->t('All Users'); ?></option>
|
||||
<optgroup label="<?php echo $l->t('Groups'); ?>">
|
||||
<?php foreach ($_['groups'] as $group): ?>
|
||||
<option value="<?php echo $group; ?>(group)" <?php if (isset($mount['applicable']['groups']) && in_array($group, $mount['applicable']['groups'])) echo 'selected="selected"'; ?>><?php echo $group; ?></option>
|
||||
@@ -113,4 +114,4 @@
|
||||
<input type="submit" name="cert_import" value="<?php echo $l->t('Import Root Certificate'); ?>" />
|
||||
<?php endif; ?>
|
||||
</fieldset>
|
||||
</form>
|
||||
</form>
|
||||
|
||||
@@ -1,43 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
$config = include('apps/files_external/tests/config.php');
|
||||
if (!is_array($config) or !isset($config['amazons3']) or !$config['amazons3']['run']) {
|
||||
abstract class Test_Filestorage_AmazonS3 extends Test_FileStorage{}
|
||||
return;
|
||||
} else {
|
||||
class Test_Filestorage_AmazonS3 extends Test_FileStorage {
|
||||
class Test_Filestorage_AmazonS3 extends Test_FileStorage {
|
||||
|
||||
private $config;
|
||||
private $id;
|
||||
private $config;
|
||||
private $id;
|
||||
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('apps/files_external/tests/config.php');
|
||||
$this->config['amazons3']['bucket'] = $id; // Make sure we have a new empty bucket to work in
|
||||
$this->instance = new OC_Filestorage_AmazonS3($this->config['amazons3']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['amazons3']) or !$this->config['amazons3']['run']) {
|
||||
$this->markTestSkipped('AmazonS3 backend not configured');
|
||||
}
|
||||
$this->config['amazons3']['bucket'] = $id; // Make sure we have a new empty bucket to work in
|
||||
$this->instance = new OC_Filestorage_AmazonS3($this->config['amazons3']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
$s3 = new AmazonS3(array('key' => $this->config['amazons3']['key'], 'secret' => $this->config['amazons3']['secret']));
|
||||
if ($s3->delete_all_objects($this->id)) {
|
||||
$s3->delete_bucket($this->id);
|
||||
|
||||
@@ -26,7 +26,7 @@ return array(
|
||||
'run'=>false,
|
||||
'user'=>'test:tester',
|
||||
'token'=>'testing',
|
||||
'host'=>'localhost:8080/auth',
|
||||
'host'=>'localhost.local:8080/auth',
|
||||
'root'=>'/',
|
||||
),
|
||||
'smb'=>array(
|
||||
|
||||
@@ -6,22 +6,21 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$config=include('files_external/tests/config.php');
|
||||
if(!is_array($config) or !isset($config['dropbox']) or !$config['dropbox']['run']) {
|
||||
abstract class Test_Filestorage_Dropbox extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_Dropbox extends Test_FileStorage {
|
||||
private $config;
|
||||
class Test_Filestorage_Dropbox extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('files_external/tests/config.php');
|
||||
$this->config['dropbox']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_Dropbox($this->config['dropbox']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['dropbox']) or !$this->config['dropbox']['run']) {
|
||||
$this->markTestSkipped('Dropbox backend not configured');
|
||||
}
|
||||
$this->config['dropbox']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_Dropbox($this->config['dropbox']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
$this->instance->unlink('/');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,40 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$config=include('apps/files_external/tests/config.php');
|
||||
if(!is_array($config) or !isset($config['ftp']) or !$config['ftp']['run']) {
|
||||
abstract class Test_Filestorage_FTP extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_FTP extends Test_FileStorage {
|
||||
private $config;
|
||||
class Test_Filestorage_FTP extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('apps/files_external/tests/config.php');
|
||||
$this->config['ftp']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_FTP($this->config['ftp']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['ftp']) or !$this->config['ftp']['run']) {
|
||||
$this->markTestSkipped('FTP backend not configured');
|
||||
}
|
||||
$this->config['ftp']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_FTP($this->config['ftp']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
OCP\Files::rmdirr($this->instance->constructUrl(''));
|
||||
}
|
||||
}
|
||||
|
||||
public function testConstructUrl(){
|
||||
$config = array ( 'host' => 'localhost', 'user' => 'ftp', 'password' => 'ftp', 'root' => '/', 'secure' => false );
|
||||
$instance = new OC_Filestorage_FTP($config);
|
||||
$this->assertEqual('ftp://ftp:ftp@localhost/', $instance->constructUrl(''));
|
||||
|
||||
$config['secure'] = true;
|
||||
$instance = new OC_Filestorage_FTP($config);
|
||||
$this->assertEqual('ftps://ftp:ftp@localhost/', $instance->constructUrl(''));
|
||||
|
||||
$config['secure'] = 'false';
|
||||
$instance = new OC_Filestorage_FTP($config);
|
||||
$this->assertEqual('ftp://ftp:ftp@localhost/', $instance->constructUrl(''));
|
||||
|
||||
$config['secure'] = 'true';
|
||||
$instance = new OC_Filestorage_FTP($config);
|
||||
$this->assertEqual('ftps://ftp:ftp@localhost/', $instance->constructUrl(''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
* ownCloud
|
||||
*
|
||||
* @author Michael Gapczynski
|
||||
* @copyright 2012 Michael Gapczynski mtgap@owncloud.com
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
$config=include('apps/files_external/tests/config.php');
|
||||
if(!is_array($config) or !isset($config['google']) or !$config['google']['run']) {
|
||||
abstract class Test_Filestorage_Google extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_Google extends Test_FileStorage {
|
||||
class Test_Filestorage_Google extends Test_FileStorage {
|
||||
|
||||
private $config;
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('apps/files_external/tests/config.php');
|
||||
$this->config['google']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_Google($this->config['google']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['google']) or !$this->config['google']['run']) {
|
||||
$this->markTestSkipped('Google backend not configured');
|
||||
}
|
||||
$this->config['google']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_Google($this->config['google']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
$this->instance->rmdir('/');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,23 +6,21 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$config=include('apps/files_external/tests/config.php');
|
||||
class Test_Filestorage_SMB extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
if(!is_array($config) or !isset($config['smb']) or !$config['smb']['run']) {
|
||||
abstract class Test_Filestorage_SMB extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_SMB extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('apps/files_external/tests/config.php');
|
||||
$this->config['smb']['root'].=$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_SMB($this->config['smb']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['smb']) or !$this->config['smb']['run']) {
|
||||
$this->markTestSkipped('Samba backend not configured');
|
||||
}
|
||||
$this->config['smb']['root'] .= $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_SMB($this->config['smb']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
OCP\Files::rmdirr($this->instance->constructUrl(''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,23 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$config=include('apps/files_external/tests/config.php');
|
||||
if(!is_array($config) or !isset($config['swift']) or !$config['swift']['run']) {
|
||||
abstract class Test_Filestorage_SWIFT extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_SWIFT extends Test_FileStorage {
|
||||
private $config;
|
||||
class Test_Filestorage_SWIFT extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('apps/files_external/tests/config.php');
|
||||
$this->config['swift']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_SWIFT($this->config['swift']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['swift']) or !$this->config['swift']['run']) {
|
||||
$this->markTestSkipped('OpenStack SWIFT backend not configured');
|
||||
}
|
||||
$this->config['swift']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_SWIFT($this->config['swift']);
|
||||
}
|
||||
|
||||
|
||||
public function tearDown() {
|
||||
$this->instance->rmdir('');
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
$this->instance->rmdir('');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,21 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
$config=include('apps/files_external/tests/config.php');
|
||||
if(!is_array($config) or !isset($config['webdav']) or !$config['webdav']['run']) {
|
||||
abstract class Test_Filestorage_DAV extends Test_FileStorage{}
|
||||
return;
|
||||
}else{
|
||||
class Test_Filestorage_DAV extends Test_FileStorage {
|
||||
private $config;
|
||||
class Test_Filestorage_DAV extends Test_FileStorage {
|
||||
private $config;
|
||||
|
||||
public function setUp() {
|
||||
$id=uniqid();
|
||||
$this->config=include('apps/files_external/tests/config.php');
|
||||
$this->config['webdav']['root'].='/'.$id;//make sure we have an new empty folder to work in
|
||||
$this->instance=new OC_Filestorage_DAV($this->config['webdav']);
|
||||
public function setUp() {
|
||||
$id = uniqid();
|
||||
$this->config = include('files_external/tests/config.php');
|
||||
if (!is_array($this->config) or !isset($this->config['webdav']) or !$this->config['webdav']['run']) {
|
||||
$this->markTestSkipped('WebDAV backend not configured');
|
||||
}
|
||||
$this->config['webdav']['root'] .= '/' . $id; //make sure we have an new empty folder to work in
|
||||
$this->instance = new OC_Filestorage_DAV($this->config['webdav']);
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
public function tearDown() {
|
||||
if ($this->instance) {
|
||||
$this->instance->rmdir('/');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
OC::$CLASSPATH['OC_Share_Backend_File'] = "apps/files_sharing/lib/share/file.php";
|
||||
OC::$CLASSPATH['OC_Share_Backend_Folder'] = 'apps/files_sharing/lib/share/folder.php';
|
||||
OC::$CLASSPATH['OC_Filestorage_Shared'] = "apps/files_sharing/lib/sharedstorage.php";
|
||||
OC::$CLASSPATH['OC_Files_Sharing_Util'] = "apps/files_sharing/lib/util.php";
|
||||
OCP\Util::connectHook('OC_Filesystem', 'setup', 'OC_Filestorage_Shared', 'setup');
|
||||
OCP\Share::registerBackend('file', 'OC_Share_Backend_File');
|
||||
OCP\Share::registerBackend('folder', 'OC_Share_Backend_Folder', 'file');
|
||||
|
||||
@@ -55,6 +55,7 @@ if (version_compare($installedVersion, '0.3', '<')) {
|
||||
OC_Util::tearDownFS();
|
||||
}
|
||||
}
|
||||
OC_User::setUserId(null);
|
||||
if ($update_error) {
|
||||
OCP\Util::writeLog('files_sharing', 'There were some problems upgrading the sharing of files', OCP\Util::ERROR);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined') {
|
||||
if (typeof OC.Share !== 'undefined' && typeof FileActions !== 'undefined' && !publicListView) {
|
||||
OC.Share.loadIcons('file');
|
||||
FileActions.register('all', 'Share', OC.PERMISSION_READ, function(filename) {
|
||||
// Return the correct sharing icon
|
||||
@@ -46,7 +46,7 @@ $(document).ready(function() {
|
||||
var appendTo = $(tr).find('td.filename');
|
||||
// Check if drop down is already visible for a different file
|
||||
if (OC.Share.droppedDown) {
|
||||
if (item != $('#dropdown').data('item')) {
|
||||
if ($(tr).data('id') != $('#dropdown').attr('data-item-source')) {
|
||||
OC.Share.hideDropDown(function () {
|
||||
$(tr).addClass('mouseOver');
|
||||
OC.Share.showDropDown(itemType, $(tr).data('id'), appendTo, true, possiblePermissions);
|
||||
|
||||
@@ -113,7 +113,10 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
|
||||
return false;
|
||||
} else if ($source = $this->getSourcePath($path)) {
|
||||
$storage = OC_Filesystem::getStorage($source);
|
||||
return $storage->mkdir($this->getInternalPath($source));
|
||||
if( ($storage->mkdir($this->getInternalPath($source))) ) {
|
||||
$this->updateFSCache($path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -296,10 +299,15 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
|
||||
'target' => $this->sharedFolder.$path,
|
||||
'source' => $source,
|
||||
);
|
||||
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info);
|
||||
OCP\Util::emitHook('OC_Filestorage_Shared', 'file_put_contents', $info);
|
||||
$parts = explode('/', $source, 4);
|
||||
$user = $parts[1];
|
||||
$intPath = '/'.$parts[3];
|
||||
$storage = OC_Filesystem::getStorage($source);
|
||||
$result = $storage->file_put_contents($this->getInternalPath($source), $data);
|
||||
return $result;
|
||||
if( ( $result = $storage->file_put_contents($this->getInternalPath($source), $data) ) ) {
|
||||
$this->updateFSCache($path);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -368,17 +376,18 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
|
||||
|
||||
public function fopen($path, $mode) {
|
||||
if ($source = $this->getSourcePath($path)) {
|
||||
$write = false;
|
||||
switch ($mode) {
|
||||
case 'w':
|
||||
case 'wb':
|
||||
case 'w+':
|
||||
case 'wb+': $write = true;
|
||||
case 'r+':
|
||||
case 'rb+':
|
||||
case 'w+':
|
||||
case 'wb+':
|
||||
case 'x+':
|
||||
case 'xb+':
|
||||
case 'a+':
|
||||
case 'ab+':
|
||||
case 'w':
|
||||
case 'wb':
|
||||
case 'x':
|
||||
case 'xb':
|
||||
case 'a':
|
||||
@@ -394,6 +403,14 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
|
||||
);
|
||||
OCP\Util::emitHook('OC_Filestorage_Shared', 'fopen', $info);
|
||||
$storage = OC_Filesystem::getStorage($source);
|
||||
|
||||
$parts = explode('/', $source, 4);
|
||||
$user = $parts[1];
|
||||
$intPath = '/'.$parts[3];
|
||||
|
||||
if ( $write && $storage->touch($this->getInternalPath($source)) ) {
|
||||
$this->updateFSCache($path);
|
||||
}
|
||||
return $storage->fopen($this->getInternalPath($source), $mode);
|
||||
}
|
||||
return false;
|
||||
@@ -447,4 +464,16 @@ class OC_Filestorage_Shared extends OC_Filestorage_Common {
|
||||
//TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
private function updateFSCache($path) {
|
||||
$source = $this->getSourcePath($path);
|
||||
$parts = explode('/', $source, 4);
|
||||
$user = $parts[1];
|
||||
$intPath = '/'.$parts[3];
|
||||
|
||||
$mtime = $this->filemtime($path);
|
||||
$size = $this->filesize($path);
|
||||
$mime = $this->getMimeType($path);
|
||||
OC_FileCache::put($intPath ,array('user'=>$user, 'size'=>$size, 'mtime'=>$mtime, 'mimetype'=>$mime, 'writable'=>true),'/'.$user.'/files');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Bjoern Schiessle
|
||||
* @copyright 2012 Bjoern Schiessle schiessle@owncloud.com
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
class OC_Files_Sharing_Util {
|
||||
|
||||
private static $files = array();
|
||||
|
||||
/**
|
||||
* @brief Get the source file path and the permissions granted for a shared file
|
||||
* @param string Shared target file path
|
||||
* @return Returns array with the keys path and permissions or false if not found
|
||||
*/
|
||||
private static function getFile($target) {
|
||||
$target = '/'.$target;
|
||||
$target = rtrim($target, '/');
|
||||
if (isset(self::$files[$target])) {
|
||||
return self::$files[$target];
|
||||
} else {
|
||||
$pos = strpos($target, '/', 1);
|
||||
// Get shared folder name
|
||||
if ($pos !== false) {
|
||||
$folder = substr($target, 0, $pos);
|
||||
if (isset(self::$files[$folder])) {
|
||||
$file = self::$files[$folder];
|
||||
} else {
|
||||
$file = OCP\Share::getItemSharedWith('folder', $folder, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
|
||||
}
|
||||
if ($file) {
|
||||
self::$files[$target]['path'] = $file['path'].substr($target, strlen($folder));
|
||||
self::$files[$target]['permissions'] = $file['permissions'];
|
||||
return self::$files[$target];
|
||||
}
|
||||
} else {
|
||||
$file = OCP\Share::getItemSharedWith('file', $target, OC_Share_Backend_File::FORMAT_SHARED_STORAGE);
|
||||
if ($file) {
|
||||
self::$files[$target] = $file;
|
||||
return self::$files[$target];
|
||||
}
|
||||
}
|
||||
OCP\Util::writeLog('files_sharing', 'File source not found for: '.$target, OCP\Util::ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the source file path for a shared file
|
||||
* @param string Shared target file path
|
||||
* @return Returns source file path or false if not found
|
||||
*/
|
||||
public static function getSourcePath($target) {
|
||||
$file = self::getFile($target);
|
||||
if (isset($file['path'])) {
|
||||
$uid = substr($file['path'], 1, strpos($file['path'], '/', 1) - 1);
|
||||
OC_Filesystem::mount('OC_Filestorage_Local', array('datadir' => OC_User::getHome($uid)), $uid);
|
||||
return $file['path'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+237
-150
@@ -19,174 +19,261 @@ if (isset($_GET['token'])) {
|
||||
\OCP\Util::writeLog('files_sharing', 'You have files that are shared by link originating from ownCloud 4.0. Redistribute the new links, because backwards compatibility will be removed in ownCloud 5.', \OCP\Util::WARN);
|
||||
}
|
||||
}
|
||||
// Enf of backward compatibility
|
||||
|
||||
if (isset($_GET['file']) || isset($_GET['dir'])) {
|
||||
function getID($path) {
|
||||
// use the share table from the db to find the item source if the file was reshared because shared files
|
||||
// are not stored in the file cache.
|
||||
if (substr(OC_Filesystem::getMountPoint($path), -7, 6) == "Shared") {
|
||||
$path_parts = explode('/', $path, 5);
|
||||
$user = $path_parts[1];
|
||||
$intPath = '/'.$path_parts[4];
|
||||
$query = \OC_DB::prepare('SELECT `item_source` FROM `*PREFIX*share` WHERE `uid_owner` = ? AND `file_target` = ? ');
|
||||
$result = $query->execute(array($user, $intPath));
|
||||
$row = $result->fetchRow();
|
||||
$fileSource = $row['item_source'];
|
||||
} else {
|
||||
$fileSource = OC_Filecache::getId($path, '');
|
||||
}
|
||||
|
||||
return $fileSource;
|
||||
}
|
||||
// End of backward compatibility
|
||||
|
||||
/**
|
||||
* lookup file path and owner by fetching it from the fscache
|
||||
* needed becaus OC_FileCache::getPath($id, $user) already requires the user
|
||||
* @param int $id
|
||||
* @return array
|
||||
*/
|
||||
function getPathAndUser($id) {
|
||||
$query = \OC_DB::prepare('SELECT `user`, `path` FROM `*PREFIX*fscache` WHERE `id` = ?');
|
||||
$result = $query->execute(array($id));
|
||||
$row = $result->fetchRow();
|
||||
return $row;
|
||||
}
|
||||
|
||||
|
||||
if (isset($_GET['t'])) {
|
||||
$token = $_GET['t'];
|
||||
$linkItem = OCP\Share::getShareByToken($token);
|
||||
if (is_array($linkItem) && isset($linkItem['uid_owner'])) {
|
||||
// seems to be a valid share
|
||||
$type = $linkItem['item_type'];
|
||||
$fileSource = $linkItem['file_source'];
|
||||
$shareOwner = $linkItem['uid_owner'];
|
||||
|
||||
if (OCP\User::userExists($shareOwner) && $fileSource != -1 ) {
|
||||
|
||||
$pathAndUser = getPathAndUser($linkItem['file_source']);
|
||||
$fileOwner = $pathAndUser['user'];
|
||||
|
||||
//if this is a reshare check the file owner also exists
|
||||
if ($shareOwner != $fileOwner && ! OCP\User::userExists($fileOwner)) {
|
||||
OCP\Util::writeLog('share', 'original file owner '.$fileOwner.' does not exist for share '.$linkItem['id'], \OCP\Util::ERROR);
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
|
||||
//mount filesystem of file owner
|
||||
OC_Util::setupFS($fileOwner);
|
||||
}
|
||||
}
|
||||
} else if (isset($_GET['file']) || isset($_GET['dir'])) {
|
||||
OCP\Util::writeLog('share', 'Missing token, trying fallback file/dir links', \OCP\Util::DEBUG);
|
||||
if (isset($_GET['dir'])) {
|
||||
$type = 'folder';
|
||||
$path = $_GET['dir'];
|
||||
if(strlen($path)>1 and substr($path, -1, 1)==='/') {
|
||||
$path=substr($path, 0, -1);
|
||||
}
|
||||
$baseDir = $path;
|
||||
$dir = $baseDir;
|
||||
} else {
|
||||
$type = 'file';
|
||||
$path = $_GET['file'];
|
||||
if(strlen($path)>1 and substr($path, -1, 1)==='/') {
|
||||
$path=substr($path, 0, -1);
|
||||
}
|
||||
}
|
||||
$uidOwner = substr($path, 1, strpos($path, '/', 1) - 1);
|
||||
if (OCP\User::userExists($uidOwner)) {
|
||||
OC_Util::setupFS($uidOwner);
|
||||
$fileSource = OC_Filecache::getId($path, '');
|
||||
if ($fileSource != -1 && ($linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $uidOwner))) {
|
||||
// TODO Fix in the getItems
|
||||
if (!isset($linkItem['item_type']) || $linkItem['item_type'] != $type) {
|
||||
$shareOwner = substr($path, 1, strpos($path, '/', 1) - 1);
|
||||
|
||||
if (OCP\User::userExists($shareOwner)) {
|
||||
OC_Util::setupFS($shareOwner);
|
||||
$fileSource = getID($path);
|
||||
if ($fileSource != -1 ) {
|
||||
$linkItem = OCP\Share::getItemSharedWithByLink($type, $fileSource, $shareOwner);
|
||||
$pathAndUser['path'] = $path;
|
||||
$path_parts = explode('/', $path, 5);
|
||||
$pathAndUser['user'] = $path_parts[1];
|
||||
$fileOwner = $path_parts[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($linkItem) {
|
||||
if (!isset($linkItem['item_type'])) {
|
||||
OCP\Util::writeLog('share', 'No item type set for share id: '.$linkItem['id'], \OCP\Util::ERROR);
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
if (isset($linkItem['share_with'])) {
|
||||
// Authenticate share_with
|
||||
$url = OCP\Util::linkToPublic('files').'&t='.$token;
|
||||
if (isset($_GET['file'])) {
|
||||
$url .= '&file='.urlencode($_GET['file']);
|
||||
} else if (isset($_GET['dir'])) {
|
||||
$url .= '&dir='.urlencode($_GET['dir']);
|
||||
}
|
||||
if (isset($_POST['password'])) {
|
||||
$password = $_POST['password'];
|
||||
if ($linkItem['share_type'] == OCP\Share::SHARE_TYPE_LINK) {
|
||||
// Check Password
|
||||
$forcePortable = (CRYPT_BLOWFISH != 1);
|
||||
$hasher = new PasswordHash(8, $forcePortable);
|
||||
if (!($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $linkItem['share_with']))) {
|
||||
$tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest');
|
||||
$tmpl->assign('URL', $url);
|
||||
$tmpl->assign('error', true);
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
} else {
|
||||
// Save item id in session for future requests
|
||||
$_SESSION['public_link_authenticated'] = $linkItem['id'];
|
||||
}
|
||||
} else {
|
||||
OCP\Util::writeLog('share', 'Unknown share type '.$linkItem['share_type'].' for share id '.$linkItem['id'], \OCP\Util::ERROR);
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
if (isset($linkItem['share_with'])) {
|
||||
// Check password
|
||||
if (isset($_POST['password'])) {
|
||||
$password = $_POST['password'];
|
||||
$storedHash = $linkItem['share_with'];
|
||||
$forcePortable = (CRYPT_BLOWFISH != 1);
|
||||
$hasher = new PasswordHash(8, $forcePortable);
|
||||
if (!($hasher->CheckPassword($password.OC_Config::getValue('passwordsalt', ''), $storedHash))) {
|
||||
$tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest');
|
||||
$tmpl->assign('URL', OCP\Util::linkToPublic('files').'&file='.$_GET['file']);
|
||||
$tmpl->assign('error', true);
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
} else {
|
||||
// Save item id in session for future requests
|
||||
$_SESSION['public_link_authenticated'] = $linkItem['id'];
|
||||
}
|
||||
// Check if item id is set in session
|
||||
} else if (!isset($_SESSION['public_link_authenticated']) || $_SESSION['public_link_authenticated'] !== $linkItem['id']) {
|
||||
// Prompt for password
|
||||
$tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest');
|
||||
$tmpl->assign('URL', OCP\Util::linkToPublic('files').'&file='.$_GET['file']);
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
}
|
||||
$path = $linkItem['path'];
|
||||
if (isset($_GET['path'])) {
|
||||
$path .= $_GET['path'];
|
||||
$dir .= $_GET['path'];
|
||||
if (!OC_Filesystem::file_exists($path)) {
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
}
|
||||
// Download the file
|
||||
if (isset($_GET['download'])) {
|
||||
if (isset($_GET['dir'])) {
|
||||
if ( isset($_GET['files']) ) { // download selected files
|
||||
OC_Files::get($path, $_GET['files'], $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
} else if (isset($_GET['path']) && $_GET['path'] != '' ) { // download a file from a shared directory
|
||||
OC_Files::get('', $path, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
} else { // download the whole shared directory
|
||||
OC_Files::get($path, '', $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
}
|
||||
} else { // download a single shared file
|
||||
OC_Files::get("", $path, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
}
|
||||
|
||||
} else {
|
||||
OCP\Util::addStyle('files_sharing', 'public');
|
||||
OCP\Util::addScript('files_sharing', 'public');
|
||||
OCP\Util::addScript('files', 'fileactions');
|
||||
$tmpl = new OCP\Template('files_sharing', 'public', 'base');
|
||||
$tmpl->assign('owner', $uidOwner);
|
||||
// Show file list
|
||||
if (OC_Filesystem::is_dir($path)) {
|
||||
OCP\Util::addStyle('files', 'files');
|
||||
OCP\Util::addScript('files', 'files');
|
||||
OCP\Util::addScript('files', 'filelist');
|
||||
$files = array();
|
||||
$rootLength = strlen($baseDir) + 1;
|
||||
foreach (OC_Files::getDirectoryContent($path) as $i) {
|
||||
$i['date'] = OCP\Util::formatDate($i['mtime']);
|
||||
if ($i['type'] == 'file') {
|
||||
$fileinfo = pathinfo($i['name']);
|
||||
$i['basename'] = $fileinfo['filename'];
|
||||
$i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : '';
|
||||
}
|
||||
$i['directory'] = '/'.substr('/'.$uidOwner.'/files'.$i['directory'], $rootLength);
|
||||
if ($i['directory'] == '/') {
|
||||
$i['directory'] = '';
|
||||
}
|
||||
$i['permissions'] = OCP\Share::PERMISSION_READ;
|
||||
$files[] = $i;
|
||||
}
|
||||
// Make breadcrumb
|
||||
$breadcrumb = array();
|
||||
$pathtohere = '';
|
||||
$count = 1;
|
||||
foreach (explode('/', $dir) as $i) {
|
||||
if ($i != '') {
|
||||
if ($i != $baseDir) {
|
||||
$pathtohere .= '/'.$i;
|
||||
}
|
||||
if ( strlen($pathtohere) < strlen($_GET['dir'])) {
|
||||
continue;
|
||||
}
|
||||
$breadcrumb[] = array('dir' => str_replace($_GET['dir'], "", $pathtohere, $count), 'name' => $i);
|
||||
}
|
||||
}
|
||||
$list = new OCP\Template('files', 'part.list', '');
|
||||
$list->assign('files', $files, false);
|
||||
$list->assign('baseURL', OCP\Util::linkToPublic('files').'&dir='.$_GET['dir'].'&path=', false);
|
||||
$list->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.$_GET['dir'].'&path=', false);
|
||||
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '' );
|
||||
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
|
||||
$breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files').'&dir='.$_GET['dir'].'&path=', false);
|
||||
$folder = new OCP\Template('files', 'index', '');
|
||||
$folder->assign('fileList', $list->fetchPage(), false);
|
||||
$folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
|
||||
$folder->assign('dir', basename($dir));
|
||||
$folder->assign('isCreatable', false);
|
||||
$folder->assign('permissions', 0);
|
||||
$folder->assign('files', $files);
|
||||
$folder->assign('uploadMaxFilesize', 0);
|
||||
$folder->assign('uploadMaxHumanFilesize', 0);
|
||||
$folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
$tmpl->assign('folder', $folder->fetchPage(), false);
|
||||
$tmpl->assign('uidOwner', $uidOwner);
|
||||
$tmpl->assign('dir', basename($dir));
|
||||
$tmpl->assign('filename', basename($path));
|
||||
$tmpl->assign('mimetype', OC_Filesystem::getMimeType($path));
|
||||
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
if (isset($_GET['path'])) {
|
||||
$getPath = $_GET['path'];
|
||||
} else {
|
||||
$getPath = '';
|
||||
}
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.$_GET['dir'].'&path='.$getPath);
|
||||
} else {
|
||||
// Show file preview if viewer is available
|
||||
$tmpl->assign('uidOwner', $uidOwner);
|
||||
$tmpl->assign('dir', dirname($path));
|
||||
$tmpl->assign('filename', basename($path));
|
||||
$tmpl->assign('mimetype', OC_Filesystem::getMimeType($path));
|
||||
if ($type == 'file') {
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&file='.$_GET['file'].'&download');
|
||||
} else {
|
||||
if (isset($_GET['path'])) {
|
||||
$getPath = $_GET['path'];
|
||||
} else {
|
||||
$getPath = '';
|
||||
}
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').'&download&dir='.$_GET['dir'].'&path='.$getPath);
|
||||
}
|
||||
}
|
||||
$tmpl->printPage();
|
||||
}
|
||||
// Check if item id is set in session
|
||||
} else if (!isset($_SESSION['public_link_authenticated']) || $_SESSION['public_link_authenticated'] !== $linkItem['id']) {
|
||||
// Prompt for password
|
||||
$tmpl = new OCP\Template('files_sharing', 'authenticate', 'guest');
|
||||
$tmpl->assign('URL', $url);
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
}
|
||||
$basePath = substr($pathAndUser['path'] , strlen('/'.$fileOwner.'/files'));
|
||||
$path = $basePath;
|
||||
if (isset($_GET['path'])) {
|
||||
$path .= $_GET['path'];
|
||||
}
|
||||
if (!$path || !OC_Filesystem::isValidPath($path) || !OC_Filesystem::file_exists($path)) {
|
||||
OCP\Util::writeLog('share', 'Invalid path '.$path.' for share id '.$linkItem['id'], \OCP\Util::ERROR);
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
$tmpl->printPage();
|
||||
exit();
|
||||
}
|
||||
$dir = dirname($path);
|
||||
$file = basename($path);
|
||||
// Download the file
|
||||
if (isset($_GET['download'])) {
|
||||
if (isset($_GET['path']) && $_GET['path'] !== '' ) {
|
||||
if ( isset($_GET['files']) ) { // download selected files
|
||||
OC_Files::get($path, $_GET['files'], $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
} else if (isset($_GET['path']) && $_GET['path'] != '' ) { // download a file from a shared directory
|
||||
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
} else { // download the whole shared directory
|
||||
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
}
|
||||
} else { // download a single shared file
|
||||
OC_Files::get($dir, $file, $_SERVER['REQUEST_METHOD'] == 'HEAD' ? true : false);
|
||||
}
|
||||
|
||||
} else {
|
||||
OCP\Util::addStyle('files_sharing', 'public');
|
||||
OCP\Util::addScript('files_sharing', 'public');
|
||||
OCP\Util::addScript('files', 'fileactions');
|
||||
$tmpl = new OCP\Template('files_sharing', 'public', 'base');
|
||||
$tmpl->assign('uidOwner', $shareOwner);
|
||||
$tmpl->assign('dir', $dir);
|
||||
$tmpl->assign('filename', $file);
|
||||
$tmpl->assign('mimetype', OC_Filesystem::getMimeType($path));
|
||||
if (isset($_GET['path'])) {
|
||||
$getPath = $_GET['path'];
|
||||
} else {
|
||||
$getPath = '';
|
||||
}
|
||||
//
|
||||
$urlLinkIdentifiers= (isset($token)?'&t='.$token:'').(isset($_GET['dir'])?'&dir='.$_GET['dir']:'').(isset($_GET['file'])?'&file='.$_GET['file']:'');
|
||||
// Show file list
|
||||
if (OC_Filesystem::is_dir($path)) {
|
||||
OCP\Util::addStyle('files', 'files');
|
||||
OCP\Util::addScript('files', 'files');
|
||||
OCP\Util::addScript('files', 'filelist');
|
||||
$files = array();
|
||||
$rootLength = strlen($basePath) + 1;
|
||||
foreach (OC_Files::getDirectoryContent($path) as $i) {
|
||||
$i['date'] = OCP\Util::formatDate($i['mtime']);
|
||||
if ($i['type'] == 'file') {
|
||||
$fileinfo = pathinfo($i['name']);
|
||||
$i['basename'] = $fileinfo['filename'];
|
||||
$i['extension'] = isset($fileinfo['extension']) ? ('.'.$fileinfo['extension']) : '';
|
||||
}
|
||||
$i['directory'] = '/'.substr($i['directory'], $rootLength);
|
||||
if ($i['directory'] == '/') {
|
||||
$i['directory'] = '';
|
||||
}
|
||||
$i['permissions'] = OCP\Share::PERMISSION_READ;
|
||||
$files[] = $i;
|
||||
}
|
||||
// Make breadcrumb
|
||||
$breadcrumb = array();
|
||||
$pathtohere = '';
|
||||
|
||||
//add base breadcrumb
|
||||
$breadcrumb[] = array('dir' => '/', 'name' => basename($basePath));
|
||||
|
||||
//add subdir breadcrumbs
|
||||
foreach (explode('/', urldecode($getPath)) as $i) {
|
||||
if ($i != '') {
|
||||
$pathtohere .= '/'.$i;
|
||||
$breadcrumb[] = array('dir' => $pathtohere, 'name' => $i);
|
||||
}
|
||||
}
|
||||
|
||||
$list = new OCP\Template('files', 'part.list', '');
|
||||
$list->assign('files', $files, false);
|
||||
$list->assign('publicListView', true);
|
||||
$list->assign('baseURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&path=', false);
|
||||
$list->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path=', false);
|
||||
$breadcrumbNav = new OCP\Template('files', 'part.breadcrumb', '' );
|
||||
$breadcrumbNav->assign('breadcrumb', $breadcrumb, false);
|
||||
$breadcrumbNav->assign('baseURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&path=', false);
|
||||
$folder = new OCP\Template('files', 'index', '');
|
||||
$folder->assign('fileList', $list->fetchPage(), false);
|
||||
$folder->assign('breadcrumb', $breadcrumbNav->fetchPage(), false);
|
||||
$folder->assign('dir', basename($dir));
|
||||
$folder->assign('isCreatable', false);
|
||||
$folder->assign('permissions', 0);
|
||||
$folder->assign('files', $files);
|
||||
$folder->assign('uploadMaxFilesize', 0);
|
||||
$folder->assign('uploadMaxHumanFilesize', 0);
|
||||
$folder->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
$tmpl->assign('folder', $folder->fetchPage(), false);
|
||||
$tmpl->assign('allowZipDownload', intval(OCP\Config::getSystemValue('allowZipDownload', true)));
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path='.urlencode($getPath));
|
||||
} else {
|
||||
// Show file preview if viewer is available
|
||||
if ($type == 'file') {
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download');
|
||||
} else {
|
||||
$tmpl->assign('downloadURL', OCP\Util::linkToPublic('files').$urlLinkIdentifiers.'&download&path='.urlencode($getPath));
|
||||
}
|
||||
}
|
||||
$tmpl->printPage();
|
||||
}
|
||||
exit();
|
||||
} else {
|
||||
OCP\Util::writeLog('share', 'could not resolve linkItem', \OCP\Util::DEBUG);
|
||||
}
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
$tmpl = new OCP\Template('', '404', 'guest');
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
<script type="text/javascript">
|
||||
<?php if ( array_key_exists('publicListView', $_) && $_['publicListView'] == true ) {
|
||||
echo "var publicListView = true;";
|
||||
} else {
|
||||
echo "var publicListView = false;";
|
||||
}
|
||||
?>
|
||||
</script>
|
||||
<input type="hidden" name="dir" value="<?php echo $_['dir'] ?>" id="dir">
|
||||
<input type="hidden" name="downloadURL" value="<?php echo $_['downloadURL'] ?>" id="downloadURL">
|
||||
<input type="hidden" name="filename" value="<?php echo $_['filename'] ?>" id="filename">
|
||||
|
||||
@@ -21,11 +21,11 @@ $(document).ready(function(){
|
||||
}
|
||||
,function(filename){
|
||||
// Action to perform when clicked
|
||||
if (scanFiles.scanning || !$('#dropdown').hasClass('drop-versions')){return;}//workaround to prevent additional http request block scanning feedback
|
||||
if (scanFiles.scanning){return;}//workaround to prevent additional http request block scanning feedback
|
||||
|
||||
var file = $('#dir').val()+'/'+filename;
|
||||
// Check if drop down is already visible for a different file
|
||||
if (($('#dropdown').length > 0)) {
|
||||
if (($('#dropdown').length > 0) && $('#dropdown').hasClass('drop-versions') ) {
|
||||
if (file != $('#dropdown').data('file')) {
|
||||
$('#dropdown').hide('blind', function() {
|
||||
$('#dropdown').remove();
|
||||
@@ -45,7 +45,7 @@ function createVersionsDropdown(filename, files) {
|
||||
|
||||
var historyUrl = OC.linkTo('files_versions', 'history.php') + '?path='+encodeURIComponent( $( '#dir' ).val() ).replace( /%2F/g, '/' )+'/'+encodeURIComponent( filename );
|
||||
|
||||
var html = '<div id="dropdown" class="drop drop-versions" data-file="'+files+'">';
|
||||
var html = '<div id="dropdown" class="drop drop-versions" data-file="'+escapeHTML(files)+'">';
|
||||
html += '<div id="private">';
|
||||
html += '<select data-placeholder="Saved versions" id="found_versions" class="chzen-select" style="width:16em;">';
|
||||
html += '<option value=""></option>';
|
||||
@@ -73,7 +73,6 @@ function createVersionsDropdown(filename, files) {
|
||||
$.each( versions, function(index, row ) {
|
||||
addVersion( row );
|
||||
});
|
||||
$('#found_versions').chosen();
|
||||
} else {
|
||||
$('#found_versions').hide();
|
||||
$('#makelink').hide();
|
||||
|
||||
@@ -64,7 +64,7 @@ class Hooks {
|
||||
$abs_newpath = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$params['newpath'].'.v';
|
||||
if(Storage::isversioned($rel_oldpath)) {
|
||||
$info=pathinfo($abs_newpath);
|
||||
if(!file_exists($info['dirname'])) mkdir($info['dirname'],0700,true);
|
||||
if(!file_exists($info['dirname'])) mkdir($info['dirname'],0750,true);
|
||||
$versions = Storage::getVersions($rel_oldpath);
|
||||
foreach ($versions as $v) {
|
||||
rename($abs_oldpath.$v['version'], $abs_newpath.$v['version']);
|
||||
|
||||
@@ -1,279 +1,274 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Versions
|
||||
*
|
||||
* A class to handle the versioning of files.
|
||||
*/
|
||||
|
||||
namespace OCA_Versions;
|
||||
|
||||
class Storage {
|
||||
|
||||
|
||||
// config.php configuration:
|
||||
// - files_versions
|
||||
// - files_versionsfolder
|
||||
// - files_versionsblacklist
|
||||
// - files_versionsmaxfilesize
|
||||
// - files_versionsinterval
|
||||
// - files_versionmaxversions
|
||||
//
|
||||
// todo:
|
||||
// - finish porting to OC_FilesystemView to enable network transparency
|
||||
// - add transparent compression. first test if it´s worth it.
|
||||
|
||||
const DEFAULTENABLED=true;
|
||||
const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp';
|
||||
const DEFAULTMAXFILESIZE=1048576; // 10MB
|
||||
const DEFAULTMININTERVAL=60; // 1 min
|
||||
const DEFAULTMAXVERSIONS=50;
|
||||
|
||||
private static function getUidAndFilename($filename)
|
||||
{
|
||||
if (\OCP\App::isEnabled('files_sharing')
|
||||
&& substr($filename, 0, 7) == '/Shared'
|
||||
&& $source = \OCP\Share::getItemSharedWith('file',
|
||||
substr($filename, 7),
|
||||
\OC_Share_Backend_File::FORMAT_SHARED_STORAGE)) {
|
||||
$filename = $source['path'];
|
||||
$pos = strpos($filename, '/files', 1);
|
||||
$uid = substr($filename, 1, $pos - 1);
|
||||
$filename = substr($filename, $pos + 6);
|
||||
} else {
|
||||
$uid = \OCP\User::getUser();
|
||||
}
|
||||
return array($uid, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* store a new version of a file.
|
||||
*/
|
||||
public function store($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$files_view = new \OC_FilesystemView('/'.$uid.'/files');
|
||||
$users_view = new \OC_FilesystemView('/'.$uid);
|
||||
|
||||
//check if source file already exist as version to avoid recursions.
|
||||
// todo does this check work?
|
||||
if ($users_view->file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if filename is a directory
|
||||
if($files_view->is_dir($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check filetype blacklist
|
||||
$blacklist=explode(' ',\OCP\Config::getSystemValue('files_versionsblacklist', Storage::DEFAULTBLACKLIST));
|
||||
foreach($blacklist as $bl) {
|
||||
$parts=explode('.', $filename);
|
||||
$ext=end($parts);
|
||||
if(strtolower($ext)==$bl) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// we should have a source file to work with
|
||||
if (!$files_view->file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check filesize
|
||||
if($files_view->filesize($filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval)
|
||||
if ($uid == \OCP\User::getUser()) {
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
|
||||
$matches=glob($versionsFolderName.'/'.$filename.'.v*');
|
||||
sort($matches);
|
||||
$parts=explode('.v',end($matches));
|
||||
if((end($parts)+Storage::DEFAULTMININTERVAL)>time()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create all parent folders
|
||||
$dirname = dirname($filename);
|
||||
if(!$users_view->file_exists('/files_versions/'.$dirname)) {
|
||||
$users_view->mkdir('/files_versions/'.$dirname,0700,true);
|
||||
}
|
||||
|
||||
// store a new version of a file
|
||||
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.time());
|
||||
|
||||
// expire old revisions if necessary
|
||||
Storage::expire($filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rollback to an old version of a file.
|
||||
*/
|
||||
public static function rollback($filename,$revision) {
|
||||
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$users_view = new \OC_FilesystemView('/'.$uid);
|
||||
|
||||
// rollback
|
||||
if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) {
|
||||
|
||||
return true;
|
||||
|
||||
}else{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* check if old versions of a file exist.
|
||||
*/
|
||||
public static function isversioned($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
|
||||
|
||||
// check for old versions
|
||||
$matches=glob($versionsFolderName.$filename.'.v*');
|
||||
if(count($matches)>0) {
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief get a list of all available versions of a file in descending chronological order
|
||||
* @param $filename file to find versions of, relative to the user files dir
|
||||
* @param $count number of versions to return
|
||||
* @returns array
|
||||
*/
|
||||
public static function getVersions( $filename, $count = 0 ) {
|
||||
|
||||
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsFolderName = \OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
|
||||
$versions = array();
|
||||
|
||||
// fetch for old versions
|
||||
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
|
||||
|
||||
sort( $matches );
|
||||
|
||||
$i = 0;
|
||||
|
||||
$files_view = new \OC_FilesystemView('/'.$uid.'/files');
|
||||
$local_file = $files_view->getLocalFile($filename);
|
||||
foreach( $matches as $ma ) {
|
||||
|
||||
$i++;
|
||||
$versions[$i]['cur'] = 0;
|
||||
$parts = explode( '.v', $ma );
|
||||
$versions[$i]['version'] = ( end( $parts ) );
|
||||
|
||||
// if file with modified date exists, flag it in array as currently enabled version
|
||||
( \md5_file( $ma ) == \md5_file( $local_file ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );
|
||||
|
||||
}
|
||||
|
||||
$versions = array_reverse( $versions );
|
||||
|
||||
foreach( $versions as $key => $value ) {
|
||||
|
||||
// flag the first matched file in array (which will have latest modification date) as current version
|
||||
if ( $value['fileMatch'] ) {
|
||||
|
||||
$value['cur'] = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$versions = array_reverse( $versions );
|
||||
|
||||
// only show the newest commits
|
||||
if( $count != 0 and ( count( $versions )>$count ) ) {
|
||||
|
||||
$versions = array_slice( $versions, count( $versions ) - $count );
|
||||
|
||||
}
|
||||
|
||||
return( $versions );
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
// if versioning isn't enabled then return an empty array
|
||||
return( array() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase a file's versions which exceed the set quota
|
||||
*/
|
||||
public static function expire($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath('');
|
||||
|
||||
// check for old versions
|
||||
$matches = glob( $versionsFolderName.'/'.$filename.'.v*' );
|
||||
|
||||
if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) {
|
||||
|
||||
$numberToDelete = count($matches) - \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS );
|
||||
|
||||
// delete old versions of a file
|
||||
$deleteItems = array_slice( $matches, 0, $numberToDelete );
|
||||
|
||||
foreach( $deleteItems as $de ) {
|
||||
|
||||
unlink( $versionsFolderName.'/'.$filename.'.v'.$de );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase all old versions of all user files
|
||||
* @return true/false
|
||||
*/
|
||||
public function expireAll() {
|
||||
$view = \OCP\Files::getStorage('files_versions');
|
||||
return $view->deleteAll('', true);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) 2012 Frank Karlitschek <frank@owncloud.org>
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Versions
|
||||
*
|
||||
* A class to handle the versioning of files.
|
||||
*/
|
||||
|
||||
namespace OCA_Versions;
|
||||
|
||||
class Storage {
|
||||
|
||||
|
||||
// config.php configuration:
|
||||
// - files_versions
|
||||
// - files_versionsfolder
|
||||
// - files_versionsblacklist
|
||||
// - files_versionsmaxfilesize
|
||||
// - files_versionsinterval
|
||||
// - files_versionmaxversions
|
||||
//
|
||||
// todo:
|
||||
// - finish porting to OC_FilesystemView to enable network transparency
|
||||
// - add transparent compression. first test if it´s worth it.
|
||||
|
||||
const DEFAULTENABLED=true;
|
||||
const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp';
|
||||
const DEFAULTMAXFILESIZE=1048576; // 10MB
|
||||
const DEFAULTMININTERVAL=60; // 1 min
|
||||
const DEFAULTMAXVERSIONS=50;
|
||||
|
||||
private static function getUidAndFilename($filename)
|
||||
{
|
||||
if (\OCP\App::isEnabled('files_sharing')
|
||||
&& substr($filename, 0, 7) == '/Shared'
|
||||
&& $source = \OC_Files_Sharing_Util::getSourcePath(substr($filename, 8))) {
|
||||
$pos = strpos($source, '/files', 1);
|
||||
$uid = substr($source, 1, $pos - 1);
|
||||
$filename = substr($source, $pos + 6);
|
||||
} else {
|
||||
$uid = \OCP\User::getUser();
|
||||
}
|
||||
return array($uid, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* store a new version of a file.
|
||||
*/
|
||||
public function store($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$files_view = new \OC_FilesystemView('/'. $uid .'/files');
|
||||
$users_view = new \OC_FilesystemView('/'.$uid);
|
||||
//check if source file already exist as version to avoid recursions.
|
||||
// todo does this check work?
|
||||
if ($users_view->file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if filename is a directory
|
||||
if($files_view->is_dir($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check filetype blacklist
|
||||
$blacklist=explode(' ',\OCP\Config::getSystemValue('files_versionsblacklist', Storage::DEFAULTBLACKLIST));
|
||||
foreach($blacklist as $bl) {
|
||||
$parts=explode('.', $filename);
|
||||
$ext=end($parts);
|
||||
if(strtolower($ext)==$bl) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// we should have a source file to work with
|
||||
if (!$files_view->file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check filesize
|
||||
if($files_view->filesize($filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
$versionsFolderName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('');
|
||||
|
||||
// check mininterval if the file is being modified by the owner (all shared files should be versioned despite mininterval)
|
||||
if ($uid == \OCP\User::getUser()) {
|
||||
$versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename);
|
||||
$matches=glob($versionsName.'.v*');
|
||||
sort($matches);
|
||||
$parts=explode('.v',end($matches));
|
||||
if((end($parts)+Storage::DEFAULTMININTERVAL)>time()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// create all parent folders
|
||||
$info=pathinfo($filename);
|
||||
if(!file_exists($versionsFolderName.'/'.$info['dirname'])) {
|
||||
mkdir($versionsFolderName.'/'.$info['dirname'],0750,true);
|
||||
}
|
||||
|
||||
// store a new version of a file
|
||||
$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.time());
|
||||
|
||||
// expire old revisions if necessary
|
||||
Storage::expire($filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* rollback to an old version of a file.
|
||||
*/
|
||||
public static function rollback($filename,$revision) {
|
||||
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$users_view = new \OC_FilesystemView('/'.$uid);
|
||||
|
||||
// rollback
|
||||
if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) {
|
||||
|
||||
return true;
|
||||
|
||||
}else{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* check if old versions of a file exist.
|
||||
*/
|
||||
public static function isversioned($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename);
|
||||
|
||||
// check for old versions
|
||||
$matches=glob($versionsName.'.v*');
|
||||
if(count($matches)>0) {
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief get a list of all available versions of a file in descending chronological order
|
||||
* @param $filename file to find versions of, relative to the user files dir
|
||||
* @param $count number of versions to return
|
||||
* @returns array
|
||||
*/
|
||||
public static function getVersions( $filename, $count = 0 ) {
|
||||
if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsName = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename);
|
||||
$versions = array();
|
||||
// fetch for old versions
|
||||
$matches = glob( $versionsName.'.v*' );
|
||||
|
||||
sort( $matches );
|
||||
|
||||
$i = 0;
|
||||
|
||||
$files_view = new \OC_FilesystemView('/'.$uid.'/files');
|
||||
$local_file = $files_view->getLocalFile($filename);
|
||||
foreach( $matches as $ma ) {
|
||||
|
||||
$i++;
|
||||
$versions[$i]['cur'] = 0;
|
||||
$parts = explode( '.v', $ma );
|
||||
$versions[$i]['version'] = ( end( $parts ) );
|
||||
|
||||
// if file with modified date exists, flag it in array as currently enabled version
|
||||
( \md5_file( $ma ) == \md5_file( $local_file ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 );
|
||||
|
||||
}
|
||||
|
||||
$versions = array_reverse( $versions );
|
||||
|
||||
foreach( $versions as $key => $value ) {
|
||||
|
||||
// flag the first matched file in array (which will have latest modification date) as current version
|
||||
if ( $value['fileMatch'] ) {
|
||||
|
||||
$value['cur'] = 1;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$versions = array_reverse( $versions );
|
||||
|
||||
// only show the newest commits
|
||||
if( $count != 0 and ( count( $versions )>$count ) ) {
|
||||
|
||||
$versions = array_slice( $versions, count( $versions ) - $count );
|
||||
|
||||
}
|
||||
|
||||
return( $versions );
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
// if versioning isn't enabled then return an empty array
|
||||
return( array() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase a file's versions which exceed the set quota
|
||||
*/
|
||||
public static function expire($filename) {
|
||||
if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') {
|
||||
list($uid, $filename) = self::getUidAndFilename($filename);
|
||||
$versions_fileview = new \OC_FilesystemView('/'.$uid.'/files_versions');
|
||||
|
||||
$versionsName=\OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath($filename);
|
||||
|
||||
// check for old versions
|
||||
$matches = glob( $versionsName.'.v*' );
|
||||
|
||||
if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) {
|
||||
|
||||
$numberToDelete = count($matches) - \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS );
|
||||
|
||||
// delete old versions of a file
|
||||
$deleteItems = array_slice( $matches, 0, $numberToDelete );
|
||||
|
||||
foreach( $deleteItems as $de ) {
|
||||
|
||||
unlink( $versionsName.'.v'.$de );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase all old versions of all user files
|
||||
* @return true/false
|
||||
*/
|
||||
public function expireAll() {
|
||||
$view = \OCP\Files::getStorage('files_versions');
|
||||
return $view->deleteAll('', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,6 @@ $entry = array(
|
||||
);
|
||||
|
||||
OCP\Backgroundjob::addRegularTask('OCA\user_ldap\lib\Jobs', 'updateGroups');
|
||||
if(OCP\App::isEnabled('user_webdavauth')) {
|
||||
OCP\Util::writeLog('user_ldap', 'user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour', OCP\Util::WARN);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>ldap_group_members</name>
|
||||
<name>ldap_group_members_index</name>
|
||||
<unique>true</unique>
|
||||
<field>
|
||||
<name>owncloudname</name>
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<info>
|
||||
<id>user_ldap</id>
|
||||
<name>LDAP user and group backend</name>
|
||||
<description>Authenticate Users by LDAP</description>
|
||||
<description>Authenticate users and groups by LDAP resp. Active Directoy.
|
||||
|
||||
This app is not compatible to the WebDAV user backend.</description>
|
||||
<licence>AGPL</licence>
|
||||
<author>Dominik Schmidt and Arthur Schiwon</author>
|
||||
<require>4.9</require>
|
||||
|
||||
@@ -34,22 +34,49 @@ $groupBE = new \OCA\user_ldap\GROUP_LDAP();
|
||||
$groupBE->setConnector($connector);
|
||||
|
||||
foreach($objects as $object) {
|
||||
$fetchDNSql = 'SELECT `ldap_dn`, `owncloud_name` FROM `*PREFIX*ldap_'.$object.'_mapping` WHERE `directory_uuid` = ""';
|
||||
$updateSql = 'UPDATE `*PREFIX*ldap_'.$object.'_mapping` SET `ldap_DN` = ?, `directory_uuid` = ? WHERE `ldap_dn` = ?';
|
||||
$fetchDNSql = '
|
||||
SELECT `ldap_dn`, `owncloud_name`, `directory_uuid`
|
||||
FROM `*PREFIX*ldap_'.$object.'_mapping`';
|
||||
$updateSql = '
|
||||
UPDATE `*PREFIX*ldap_'.$object.'_mapping`
|
||||
SET `ldap_DN` = ?, `directory_uuid` = ?
|
||||
WHERE `ldap_dn` = ?';
|
||||
|
||||
$query = OCP\DB::prepare($fetchDNSql);
|
||||
$res = $query->execute();
|
||||
$DNs = $res->fetchAll();
|
||||
$updateQuery = OCP\DB::prepare($updateSql);
|
||||
foreach($DNs as $dn) {
|
||||
$newDN = mb_strtolower($dn['ldap_dn'], 'UTF-8');
|
||||
if($object == 'user') {
|
||||
$newDN = escapeDN(mb_strtolower($dn['ldap_dn'], 'UTF-8'));
|
||||
if(!empty($dn['directory_uuid'])) {
|
||||
$uuid = $dn['directory_uuid'];
|
||||
} elseif($object == 'user') {
|
||||
$uuid = $userBE->getUUID($newDN);
|
||||
//fix home folder to avoid new ones depending on the configuration
|
||||
$userBE->getHome($dn['owncloud_name']);
|
||||
} else {
|
||||
$uuid = $groupBE->getUUID($newDN);
|
||||
}
|
||||
$updateQuery->execute(array($newDN, $uuid, $dn['ldap_dn']));
|
||||
try {
|
||||
$updateQuery->execute(array($newDN, $uuid, $dn['ldap_dn']));
|
||||
} catch(Exception $e) {
|
||||
\OCP\Util::writeLog('user_ldap', 'Could not update '.$object.' '.$dn['ldap_dn'].' in the mappings table. ', \OCP\Util::WARN);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function escapeDN($dn) {
|
||||
$aDN = ldap_explode_dn($dn, false);
|
||||
unset($aDN['count']);
|
||||
foreach($aDN as $key => $part) {
|
||||
$value = substr($part, strpos($part, '=')+1);
|
||||
$escapedValue = strtr($value, Array(','=>'\2c', '='=>'\3d', '+'=>'\2b',
|
||||
'<'=>'\3c', '>'=>'\3e', ';'=>'\3b', '\\'=>'\5c',
|
||||
'"'=>'\22', '#'=>'\23'));
|
||||
$part = str_replace($part, $value, $escapedValue);
|
||||
}
|
||||
$dn = implode(',', $aDN);
|
||||
|
||||
return $dn;
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.3.0.0
|
||||
0.3.0.1
|
||||
@@ -7,4 +7,9 @@
|
||||
#ldap fieldset input {
|
||||
width: 70%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ldapwarning {
|
||||
margin-left: 1.4em;
|
||||
color: #FF3B3B;
|
||||
}
|
||||
@@ -28,10 +28,11 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface {
|
||||
|
||||
public function setConnector(lib\Connection &$connection) {
|
||||
parent::setConnector($connection);
|
||||
if(empty($this->connection->ldapGroupFilter) || empty($this->connection->ldapGroupMemberAssocAttr)) {
|
||||
$this->enabled = false;
|
||||
$filter = $this->connection->ldapGroupFilter;
|
||||
$gassoc = $this->connection->ldapGroupMemberAssocAttr;
|
||||
if(!empty($filter) && !empty($gassoc)) {
|
||||
$this->enabled = true;
|
||||
}
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,12 +97,13 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface {
|
||||
if(!$this->enabled) {
|
||||
return array();
|
||||
}
|
||||
if($this->connection->isCached('getUserGroups'.$uid)) {
|
||||
return $this->connection->getFromCache('getUserGroups'.$uid);
|
||||
$cacheKey = 'getUserGroups'.$uid;
|
||||
if($this->connection->isCached($cacheKey)) {
|
||||
return $this->connection->getFromCache($cacheKey);
|
||||
}
|
||||
$userDN = $this->username2dn($uid);
|
||||
if(!$userDN) {
|
||||
$this->connection->writeToCache('getUserGroups'.$uid, array());
|
||||
$this->connection->writeToCache($cacheKey, array());
|
||||
return array();
|
||||
}
|
||||
|
||||
@@ -124,7 +126,7 @@ class GROUP_LDAP extends lib\Access implements \OCP\GroupInterface {
|
||||
));
|
||||
$groups = $this->fetchListOfGroups($filter, array($this->connection->ldapGroupDisplayName,'dn'));
|
||||
$groups = array_unique($this->ownCloudGroupNames($groups), SORT_LOCALE_STRING);
|
||||
$this->connection->writeToCache('getUserGroups'.$uid, $groups);
|
||||
$this->connection->writeToCache($cacheKey, $groups);
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
@@ -38,9 +38,11 @@ abstract class Access {
|
||||
* @brief reads a given attribute for an LDAP record identified by a DN
|
||||
* @param $dn the record in question
|
||||
* @param $attr the attribute that shall be retrieved
|
||||
* @returns the values in an array on success, false otherwise
|
||||
* if empty, just check the record's existence
|
||||
* @returns an array of values on success or an empty
|
||||
* array if $attr is empty, false otherwise
|
||||
*
|
||||
* Reads an attribute from an LDAP entry
|
||||
* Reads an attribute from an LDAP entry or check if entry exists
|
||||
*/
|
||||
public function readAttribute($dn, $attr) {
|
||||
if(!$this->checkConnection()) {
|
||||
@@ -53,12 +55,18 @@ abstract class Access {
|
||||
\OCP\Util::writeLog('user_ldap', 'LDAP resource not available.', \OCP\Util::DEBUG);
|
||||
return false;
|
||||
}
|
||||
//Slashes should only be escaped in filters, not bases.
|
||||
$dn = $this->DNasBaseParameter($dn);
|
||||
$rr = @ldap_read($cr, $dn, 'objectClass=*', array($attr));
|
||||
if(!is_resource($rr)) {
|
||||
\OCP\Util::writeLog('user_ldap', 'readAttribute '.$attr.' failed for DN '.$dn, \OCP\Util::DEBUG);
|
||||
\OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN '.$dn, \OCP\Util::DEBUG);
|
||||
//in case an error occurs , e.g. object does not exist
|
||||
return false;
|
||||
}
|
||||
if (empty($attr)) {
|
||||
\OCP\Util::writeLog('user_ldap', 'readAttribute: '.$dn.' found', \OCP\Util::DEBUG);
|
||||
return array();
|
||||
}
|
||||
$er = ldap_first_entry($cr, $rr);
|
||||
//LDAP attributes are not case sensitive
|
||||
$result = \OCP\Util::mb_array_change_key_case(ldap_get_attributes($cr, $er), MB_CASE_LOWER, 'UTF-8');
|
||||
@@ -67,7 +75,13 @@ abstract class Access {
|
||||
if(isset($result[$attr]) && $result[$attr]['count'] > 0) {
|
||||
$values = array();
|
||||
for($i=0;$i<$result[$attr]['count'];$i++) {
|
||||
$values[] = $this->resemblesDN($attr) ? $this->sanitizeDN($result[$attr][$i]) : $result[$attr][$i];
|
||||
if($this->resemblesDN($attr)) {
|
||||
$values[] = $this->sanitizeDN($result[$attr][$i]);
|
||||
} elseif(strtolower($attr) == 'objectguid') {
|
||||
$values[] = $this->convertObjectGUID2Str($result[$attr][$i]);
|
||||
} else {
|
||||
$values[] = $result[$attr][$i];
|
||||
}
|
||||
}
|
||||
return $values;
|
||||
}
|
||||
@@ -101,6 +115,21 @@ abstract class Access {
|
||||
//make comparisons and everything work
|
||||
$dn = mb_strtolower($dn, 'UTF-8');
|
||||
|
||||
//escape DN values according to RFC 2253 – this is already done by ldap_explode_dn
|
||||
//to use the DN in search filters, \ needs to be escaped to \5c additionally
|
||||
//to use them in bases, we convert them back to simple backslashes in readAttribute()
|
||||
$replacements = array(
|
||||
'\,' => '\5c2C',
|
||||
'\=' => '\5c3D',
|
||||
'\+' => '\5c2B',
|
||||
'\<' => '\5c3C',
|
||||
'\>' => '\5c3E',
|
||||
'\;' => '\5c3B',
|
||||
'\"' => '\5c22',
|
||||
'\#' => '\5c23',
|
||||
);
|
||||
$dn = str_replace(array_keys($replacements),array_values($replacements), $dn);
|
||||
|
||||
return $dn;
|
||||
}
|
||||
|
||||
@@ -209,7 +238,6 @@ abstract class Access {
|
||||
* returns the internal ownCloud name for the given LDAP DN of the user, false on DN outside of search DN
|
||||
*/
|
||||
public function dn2ocname($dn, $ldapname = null, $isUser = true) {
|
||||
$dn = $this->sanitizeDN($dn);
|
||||
$table = $this->getMapTable($isUser);
|
||||
if($isUser) {
|
||||
$fncFindMappedName = 'findMappedUser';
|
||||
@@ -255,8 +283,8 @@ abstract class Access {
|
||||
}
|
||||
$ldapname = $this->sanitizeUsername($ldapname);
|
||||
|
||||
//a new user/group! Then let's try to add it. We're shooting into the blue with the user/group name, assuming that in most cases there will not be a conflict. Otherwise an error will occur and we will continue with our second shot.
|
||||
if(($isUser && !\OCP\User::userExists($ldapname)) || (!$isUser && !\OC_Group::groupExists($ldapname))) {
|
||||
//a new user/group! Add it only if it doesn't conflict with other backend's users or existing groups
|
||||
if(($isUser && !\OCP\User::userExists($ldapname, 'OCA\\user_ldap\\USER_LDAP')) || (!$isUser && !\OC_Group::groupExists($ldapname))) {
|
||||
if($this->mapComponent($dn, $ldapname, $isUser)) {
|
||||
return $ldapname;
|
||||
}
|
||||
@@ -339,7 +367,8 @@ abstract class Access {
|
||||
$ownCloudNames = array();
|
||||
|
||||
foreach($ldapObjects as $ldapObject) {
|
||||
$ocname = $this->dn2ocname($ldapObject['dn'], $ldapObject[$nameAttribute], $isUsers);
|
||||
$nameByLDAP = isset($ldapObject[$nameAttribute]) ? $ldapObject[$nameAttribute] : null;
|
||||
$ocname = $this->dn2ocname($ldapObject['dn'], $nameByLDAP, $isUsers);
|
||||
if($ocname) {
|
||||
$ownCloudNames[] = $ocname;
|
||||
}
|
||||
@@ -405,7 +434,6 @@ abstract class Access {
|
||||
*/
|
||||
private function mapComponent($dn, $ocname, $isUser = true) {
|
||||
$table = $this->getMapTable($isUser);
|
||||
$dn = $this->sanitizeDN($dn);
|
||||
|
||||
$sqlAdjustment = '';
|
||||
$dbtype = \OCP\Config::getSystemValue('dbtype');
|
||||
@@ -503,6 +531,12 @@ abstract class Access {
|
||||
$link_resource = $this->connection->getConnectionResource();
|
||||
if(is_resource($link_resource)) {
|
||||
$sr = ldap_search($link_resource, $base, $filter, $attr);
|
||||
if(!is_resource($sr)) {
|
||||
$errmsg = '('.ldap_errno($link_resource).') ' . ldap_error($link_resource);
|
||||
$errmsg .= ', search filter: ' . $filter;
|
||||
\OCP\Util::writeLog('user_ldap', 'Search: no result resource, LDAP error message: ' . $errmsg, \OCP\Util::ERROR);
|
||||
return array();
|
||||
}
|
||||
$findings = ldap_get_entries($link_resource, $sr );
|
||||
|
||||
// if we're here, probably no connection resource is returned.
|
||||
@@ -622,6 +656,7 @@ abstract class Access {
|
||||
}
|
||||
|
||||
public function areCredentialsValid($name, $password) {
|
||||
$name = $this->DNasBaseParameter($name);
|
||||
$testConnection = clone $this->connection;
|
||||
$credentials = array(
|
||||
'ldapAgentName' => $name,
|
||||
@@ -664,6 +699,7 @@ abstract class Access {
|
||||
|
||||
public function getUUID($dn) {
|
||||
if($this->detectUuidAttribute($dn)) {
|
||||
\OCP\Util::writeLog('user_ldap', 'UUID Checking \ UUID for '.$dn.' using '. $this->connection->ldapUuidAttribute, \OCP\Util::DEBUG);
|
||||
$uuid = $this->readAttribute($dn, $this->connection->ldapUuidAttribute);
|
||||
if(!is_array($uuid) && $this->connection->ldapOverrideUuidAttribute) {
|
||||
$this->detectUuidAttribute($dn, true);
|
||||
@@ -679,4 +715,44 @@ abstract class Access {
|
||||
}
|
||||
return $uuid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief converts a binary ObjectGUID into a string representation
|
||||
* @param $oguid the ObjectGUID in it's binary form as retrieved from AD
|
||||
* @returns String
|
||||
*
|
||||
* converts a binary ObjectGUID into a string representation
|
||||
* http://www.php.net/manual/en/function.ldap-get-values-len.php#73198
|
||||
*/
|
||||
private function convertObjectGUID2Str($oguid) {
|
||||
$hex_guid = bin2hex($oguid);
|
||||
$hex_guid_to_guid_str = '';
|
||||
for($k = 1; $k <= 4; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 12 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-';
|
||||
for($k = 1; $k <= 2; ++$k) {
|
||||
$hex_guid_to_guid_str .= substr($hex_guid, 16 - 2 * $k, 2);
|
||||
}
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 16, 4);
|
||||
$hex_guid_to_guid_str .= '-' . substr($hex_guid, 20);
|
||||
|
||||
return strtoupper($hex_guid_to_guid_str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief converts a stored DN so it can be used as base parameter for LDAP queries
|
||||
* @param $dn the DN
|
||||
* @returns String
|
||||
*
|
||||
* converts a stored DN so it can be used as base parameter for LDAP queries
|
||||
* internally we store them for usage in LDAP filters
|
||||
*/
|
||||
private function DNasBaseParameter($dn) {
|
||||
return str_replace('\\5c', '\\', $dn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class Connection {
|
||||
\OCP\Util::writeLog('user_ldap', 'Set config ldapUuidAttribute to '.$value, \OCP\Util::DEBUG);
|
||||
$this->config[$name] = $value;
|
||||
if(!empty($this->configID)) {
|
||||
\OCP\Config::getAppValue($this->configID, 'ldap_uuid_attribute', $value);
|
||||
\OCP\Config::setAppValue($this->configID, 'ldap_uuid_attribute', $value);
|
||||
}
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
@@ -20,22 +20,21 @@
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
OC_Util::checkAdminUser();
|
||||
|
||||
$params = array('ldap_host', 'ldap_port', 'ldap_dn', 'ldap_agent_password', 'ldap_base', 'ldap_base_users', 'ldap_base_groups', 'ldap_userlist_filter', 'ldap_login_filter', 'ldap_group_filter', 'ldap_display_name', 'ldap_group_display_name', 'ldap_tls', 'ldap_turn_off_cert_check', 'ldap_nocase', 'ldap_quota_def', 'ldap_quota_attr', 'ldap_email_attr', 'ldap_group_member_assoc_attribute', 'ldap_cache_ttl', 'home_folder_naming_rule');
|
||||
|
||||
OCP\Util::addscript('user_ldap', 'settings');
|
||||
OCP\Util::addstyle('user_ldap', 'settings');
|
||||
|
||||
if ($_POST) {
|
||||
$clearCache = false;
|
||||
foreach($params as $param) {
|
||||
if(isset($_POST[$param])) {
|
||||
$clearCache = true;
|
||||
if('ldap_agent_password' == $param) {
|
||||
OCP\Config::setAppValue('user_ldap', $param, base64_encode($_POST[$param]));
|
||||
} elseif('ldap_cache_ttl' == $param) {
|
||||
if(OCP\Config::getAppValue('user_ldap', $param,'') != $_POST[$param]) {
|
||||
$ldap = new \OCA\user_ldap\lib\Connection('user_ldap');
|
||||
$ldap->clearCache();
|
||||
OCP\Config::setAppValue('user_ldap', $param, $_POST[$param]);
|
||||
}
|
||||
} elseif('home_folder_naming_rule' == $param) {
|
||||
$value = empty($_POST[$param]) ? 'opt:username' : 'attr:'.$_POST[$param];
|
||||
OCP\Config::setAppValue('user_ldap', $param, $value);
|
||||
@@ -54,6 +53,10 @@ if ($_POST) {
|
||||
OCP\Config::setAppValue('user_ldap', $param, 0);
|
||||
}
|
||||
}
|
||||
if($clearCache) {
|
||||
$ldap = new \OCA\user_ldap\lib\Connection('user_ldap');
|
||||
$ldap->clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
// fill template
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
<li><a href="#ldapSettings-1">LDAP Basic</a></li>
|
||||
<li><a href="#ldapSettings-2">Advanced</a></li>
|
||||
</ul>
|
||||
<?php if(OCP\App::isEnabled('user_webdavauth')) {
|
||||
echo '<p class="ldapwarning">'.$l->t('<b>Warning:</b> Apps user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour. Please ask your system administrator to disable one of them.').'</p>';
|
||||
}
|
||||
if(!function_exists('ldap_connect')) {
|
||||
echo '<p class="ldapwarning">'.$l->t('<b>Warning:</b> The PHP LDAP module needs is not installed, the backend will not work. Please ask your system administrator to install it.').'</p>';
|
||||
}
|
||||
?>
|
||||
<fieldset id="ldapSettings-1">
|
||||
<p><label for="ldap_host"><?php echo $l->t('Host');?></label><input type="text" id="ldap_host" name="ldap_host" value="<?php echo $_['ldap_host']; ?>" title="<?php echo $l->t('You can omit the protocol, except you require SSL. Then start with ldaps://');?>"></p>
|
||||
<p><label for="ldap_base"><?php echo $l->t('Base DN');?></label><input type="text" id="ldap_base" name="ldap_base" value="<?php echo $_['ldap_base']; ?>" title="<?php echo $l->t('You can specify Base DN for users and groups in the Advanced tab');?>" /></p>
|
||||
|
||||
@@ -29,11 +29,13 @@ class USER_LDAP extends lib\Access implements \OCP\UserInterface {
|
||||
|
||||
private function updateQuota($dn) {
|
||||
$quota = null;
|
||||
if(!empty($this->connection->ldapQuotaDefault)) {
|
||||
$quota = $this->connection->ldapQuotaDefault;
|
||||
$quotaDefault = $this->connection->ldapQuotaDefault;
|
||||
$quotaAttribute = $this->connection->ldapQuotaAttribute;
|
||||
if(!empty($quotaDefault)) {
|
||||
$quota = $quotaDefault;
|
||||
}
|
||||
if(!empty($this->connection->ldapQuotaAttribute)) {
|
||||
$aQuota = $this->readAttribute($dn, $this->connection->ldapQuotaAttribute);
|
||||
if(!empty($quotaAttribute)) {
|
||||
$aQuota = $this->readAttribute($dn, $quotaAttribute);
|
||||
|
||||
if($aQuota && (count($aQuota) > 0)) {
|
||||
$quota = $aQuota[0];
|
||||
@@ -46,8 +48,9 @@ class USER_LDAP extends lib\Access implements \OCP\UserInterface {
|
||||
|
||||
private function updateEmail($dn) {
|
||||
$email = null;
|
||||
if(!empty($this->connection->ldapEmailAttribute)) {
|
||||
$aEmail = $this->readAttribute($dn, $this->connection->ldapEmailAttribute);
|
||||
$emailAttribute = $this->connection->ldapEmailAttribute;
|
||||
if(!empty($emailAttribute)) {
|
||||
$aEmail = $this->readAttribute($dn, $emailAttribute);
|
||||
if($aEmail && (count($aEmail) > 0)) {
|
||||
$email = $aEmail[0];
|
||||
}
|
||||
@@ -138,9 +141,8 @@ class USER_LDAP extends lib\Access implements \OCP\UserInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
//if user really still exists, we will be able to read his objectclass
|
||||
$objcs = $this->readAttribute($dn, 'objectclass');
|
||||
if(!$objcs || empty($objcs)) {
|
||||
//check if user really still exists by reading its entry
|
||||
if(!is_array($this->readAttribute($dn, ''))) {
|
||||
$this->connection->writeToCache('userExists'.$uid, false);
|
||||
return false;
|
||||
}
|
||||
@@ -169,8 +171,19 @@ class USER_LDAP extends lib\Access implements \OCP\UserInterface {
|
||||
if(strpos($this->connection->homeFolderNamingRule, 'attr:') === 0) {
|
||||
$attr = substr($this->connection->homeFolderNamingRule, strlen('attr:'));
|
||||
$homedir = $this->readAttribute($this->username2dn($uid), $attr);
|
||||
if($homedir) {
|
||||
$homedir = \OCP\Config::getSystemValue( "datadirectory", \OC::$SERVERROOT."/data" ) . '/' . $homedir[0];
|
||||
if($homedir && isset($homedir[0])) {
|
||||
$path = $homedir[0];
|
||||
//if attribute's value is an absolute path take this, otherwise append it to data dir
|
||||
//check for / at the beginning or pattern c:\ resp. c:/
|
||||
if(
|
||||
'/' == $path[0]
|
||||
|| (3 < strlen($path) && ctype_alpha($path[0]) && $path[1] == ':' && ('\\' == $path[2] || '/' == $path[2]))
|
||||
) {
|
||||
$homedir = $path;
|
||||
} else {
|
||||
$homedir = \OCP\Config::getSystemValue( "datadirectory", \OC::$SERVERROOT."/data" ) . '/' . $homedir[0];
|
||||
}
|
||||
|
||||
\OCP\Config::setUserValue($uid, 'user_ldap', 'homedir', $homedir);
|
||||
return $homedir;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
require_once 'apps/user_webdavauth/user_webdavauth.php';
|
||||
|
||||
OC_APP::registerAdmin('user_webdavauth','settings');
|
||||
OC_APP::registerAdmin('user_webdavauth', 'settings');
|
||||
|
||||
OC_User::registerBackend("WEBDAVAUTH");
|
||||
OC_User::useBackend( "WEBDAVAUTH" );
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
<info>
|
||||
<id>user_webdavauth</id>
|
||||
<name>WebDAV user backend</name>
|
||||
<description>Authenticate Users by a WebDAV call</description>
|
||||
<version>1.0</version>
|
||||
<description>Authenticate users by a WebDAV call. You can use any WebDAV server, ownCloud server or other webserver to authenticate. It should return http 200 for right credentials and http 401 for wrong ones.
|
||||
|
||||
This app is not compatible to the LDAP user and group backend.</description>
|
||||
<licence>AGPL</licence>
|
||||
<author>Frank Karlitschek</author>
|
||||
<require>4.9</require>
|
||||
<shipped>true</shipped>
|
||||
<types>
|
||||
<authentication/>
|
||||
</types>
|
||||
</info>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1.1.0.0
|
||||
@@ -21,7 +21,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
print_r($_POST);
|
||||
OC_Util::checkAdminUser();
|
||||
|
||||
if($_POST) {
|
||||
|
||||
if(isset($_POST['webdav_url'])) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<form id="webdavauth" action="#" method="post">
|
||||
<fieldset class="personalblock">
|
||||
<legend><strong>WebDAV Authentication</strong></legend>
|
||||
<p><label for="webdav_url"><?php echo $l->t('webdav_url');?><input type="text" id="webdav_url" name="webdav_url" value="<?php echo $_['webdav_url']; ?>"></label>
|
||||
<p><label for="webdav_url"><?php echo $l->t('WebDAV URL: http://');?><input type="text" id="webdav_url" name="webdav_url" value="<?php echo $_['webdav_url']; ?>"></label>
|
||||
<input type="submit" value="Save" />
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
@@ -30,37 +30,36 @@ class OC_USER_WEBDAVAUTH extends OC_User_Backend {
|
||||
|
||||
public function createUser() {
|
||||
// Can't create user
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to create users from web frontend using WebDAV user backend',3);
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to create users from web frontend using WebDAV user backend', 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function deleteUser() {
|
||||
public function deleteUser($uid) {
|
||||
// Can't delete user
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to delete users from web frontend using WebDAV user backend',3);
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to delete users from web frontend using WebDAV user backend', 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setPassword ( $uid, $password ) {
|
||||
// We can't change user password
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to change password for users from web frontend using WebDAV user backend',3);
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to change password for users from web frontend using WebDAV user backend', 3);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkPassword( $uid, $password ) {
|
||||
|
||||
$url= 'http://'.urlencode($uid).':'.urlencode($password).'@'.$this->webdavauth_url;
|
||||
$headers = get_headers($url);
|
||||
if($headers==false) {
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to connect to WebDAV Url: "'.$this->webdavauth_url.'" ' ,3);
|
||||
OC_Log::write('OC_USER_WEBDAVAUTH', 'Not possible to connect to WebDAV Url: "'.$this->webdavauth_url.'" ', 3);
|
||||
return false;
|
||||
|
||||
}
|
||||
$returncode= substr($headers[0], 9, 3);
|
||||
|
||||
if($returncode=='401') {
|
||||
return false;
|
||||
return(false);
|
||||
}else{
|
||||
return true;
|
||||
return($uid);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,14 +67,15 @@ class OC_USER_WEBDAVAUTH extends OC_User_Backend {
|
||||
/*
|
||||
* we don´t know if a user exists without the password. so we have to return false all the time
|
||||
*/
|
||||
public function userExists( $uid ) {
|
||||
return false;
|
||||
public function userExists( $uid ){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* we don´t know the users so all we can do it return an empty array here
|
||||
*/
|
||||
public function getUsers() {
|
||||
public function getUsers($search = '', $limit = 10, $offset = 0) {
|
||||
$returnArray = array();
|
||||
|
||||
return $returnArray;
|
||||
|
||||
@@ -30,6 +30,12 @@ $CONFIG = array(
|
||||
/* Force use of HTTPS connection (true = use HTTPS) */
|
||||
"forcessl" => false,
|
||||
|
||||
/* The automatic hostname detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. You can also add a port. For example "www.example.com:88" */
|
||||
"overwritehost" => "",
|
||||
|
||||
/* The automatic protocol detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the protocol detection. For example "https" */
|
||||
"overwriteprotocol" => "",
|
||||
|
||||
/* Theme to use for ownCloud */
|
||||
"theme" => "",
|
||||
|
||||
@@ -104,4 +110,4 @@ $CONFIG = array(
|
||||
'writable' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
);
|
||||
|
||||
+50
-5
@@ -28,13 +28,19 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
|
||||
case 'share':
|
||||
if (isset($_POST['shareType']) && isset($_POST['shareWith']) && isset($_POST['permissions'])) {
|
||||
try {
|
||||
if ((int)$_POST['shareType'] === OCP\Share::SHARE_TYPE_LINK && $_POST['shareWith'] == '') {
|
||||
$shareType = (int)$_POST['shareType'];
|
||||
$shareWith = $_POST['shareWith'];
|
||||
if ($shareType === OCP\Share::SHARE_TYPE_LINK && $shareWith == '') {
|
||||
$shareWith = null;
|
||||
} else {
|
||||
$shareWith = $_POST['shareWith'];
|
||||
}
|
||||
OCP\Share::shareItem($_POST['itemType'], $_POST['itemSource'], (int)$_POST['shareType'], $shareWith, $_POST['permissions']);
|
||||
OC_JSON::success();
|
||||
|
||||
$token = OCP\Share::shareItem($_POST['itemType'], $_POST['itemSource'], $shareType, $shareWith, $_POST['permissions']);
|
||||
|
||||
if (is_string($token)) {
|
||||
OC_JSON::success(array('data' => array('token' => $token)));
|
||||
} else {
|
||||
OC_JSON::success();
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
OC_JSON::error(array('data' => array('message' => $exception->getMessage())));
|
||||
}
|
||||
@@ -63,6 +69,45 @@ if (isset($_POST['action']) && isset($_POST['itemType']) && isset($_POST['itemSo
|
||||
($return) ? OC_JSON::success() : OC_JSON::error();
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
// read post variables
|
||||
$user = OCP\USER::getUser();
|
||||
$type = $_POST['itemType'];
|
||||
$link = $_POST['link'];
|
||||
$file = $_POST['file'];
|
||||
$to_address = $_POST['toaddress'];
|
||||
|
||||
// enable l10n support
|
||||
$l = OC_L10N::get('core');
|
||||
|
||||
// setup the email
|
||||
$subject = (string)$l->t('User %s shared a file with you', $user);
|
||||
if ($type === 'dir') {
|
||||
$subject = (string)$l->t('User %s shared a folder with you', $user);
|
||||
}
|
||||
|
||||
$text = (string)$l->t('User %s shared the file "%s" with you. It is available for download here: %s', array($user, $file, $link));
|
||||
if ($type === 'dir') {
|
||||
$text = (string)$l->t('User %s shared the folder "%s" with you. It is available for download here: %s', array($user, $file, $link));
|
||||
}
|
||||
|
||||
// handle localhost installations
|
||||
$server_host = OCP\Util::getServerHost();
|
||||
if ($server_host === 'localhost') {
|
||||
$server_host = "example.com";
|
||||
}
|
||||
|
||||
$default_from = 'sharing-noreply@' . $server_host;
|
||||
$from_address = OCP\Config::getUserValue($user, 'settings', 'email', $default_from);
|
||||
|
||||
// send it out now
|
||||
try {
|
||||
OCP\Util::sendMail($to_address, $to_address, $subject, $text, $from_address, $user);
|
||||
OCP\JSON::success();
|
||||
} catch (Exception $exception) {
|
||||
OCP\JSON::error(array('data' => array('message' => $exception->getMessage())));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if (isset($_GET['fetch'])) {
|
||||
switch ($_GET['fetch']) {
|
||||
|
||||
@@ -17,6 +17,11 @@ a.unshare { float:right; display:inline; padding:.3em 0 0 .3em !important; opaci
|
||||
a.unshare:hover { opacity:1; }
|
||||
#link { border-top:1px solid #ddd; padding-top:0.5em; }
|
||||
#dropdown input[type="text"], #dropdown input[type="password"] { width:90%; }
|
||||
#dropdown form {
|
||||
font-size: 100%;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
#linkText, #linkPass, #expiration { display:none; }
|
||||
#link #showPassword img { width:12px; padding-left: 0.3em; }
|
||||
#link label, #expiration label{ padding-left: 0.5em; }
|
||||
+12
-3
@@ -42,7 +42,11 @@ OC.EventSource=function(src,data){
|
||||
}
|
||||
dataStr+='requesttoken='+OC.Request.Token;
|
||||
if(!this.useFallBack && typeof EventSource !='undefined'){
|
||||
this.source=new EventSource(src+'?'+dataStr);
|
||||
var joinChar = '&';
|
||||
if(src.indexOf('?') == -1) {
|
||||
joinChar = '?';
|
||||
}
|
||||
this.source=new EventSource(src+joinChar+dataStr);
|
||||
this.source.onmessage=function(e){
|
||||
for(var i=0;i<this.typelessListeners.length;i++){
|
||||
this.typelessListeners[i](JSON.parse(e.data));
|
||||
@@ -54,7 +58,12 @@ OC.EventSource=function(src,data){
|
||||
this.iframe=$('<iframe/>');
|
||||
this.iframe.attr('id',iframeId);
|
||||
this.iframe.hide();
|
||||
this.iframe.attr('src',src+'?fallback=true&fallback_id='+OC.EventSource.iframeCount+'&'+dataStr);
|
||||
|
||||
var joinChar = '&';
|
||||
if(src.indexOf('?') == -1) {
|
||||
joinChar = '?';
|
||||
}
|
||||
this.iframe.attr('src',src+joinChar+'fallback=true&fallback_id='+OC.EventSource.iframeCount+'&'+dataStr);
|
||||
$('body').append(this.iframe);
|
||||
this.useFallBack=true;
|
||||
OC.EventSource.iframeCount++
|
||||
@@ -90,7 +99,7 @@ OC.EventSource.prototype={
|
||||
lastLength:0,//for fallback
|
||||
listen:function(type,callback){
|
||||
if(callback && callback.call){
|
||||
|
||||
|
||||
if(type){
|
||||
if(this.useFallBack){
|
||||
if(!this.listeners[type]){
|
||||
|
||||
+10
-1
@@ -30,6 +30,15 @@ function t(app,text){
|
||||
}
|
||||
t.cache={};
|
||||
|
||||
/*
|
||||
* Sanitizes a HTML string
|
||||
* @param string
|
||||
* @return Sanitized string
|
||||
*/
|
||||
function escapeHTML(s) {
|
||||
return s.toString().split('&').join('&').split('<').join('<').split('"').join('"');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path to download a file
|
||||
* @param file The filename
|
||||
@@ -619,7 +628,7 @@ $.fn.filterAttr = function(attr_name, attr_value) {
|
||||
function humanFileSize(size) {
|
||||
var humanList = ['B', 'kB', 'MB', 'GB', 'TB'];
|
||||
// Calculate Log with base 1024: size = 1024 ** order
|
||||
var order = Math.floor(Math.log(size) / Math.log(1024));
|
||||
var order = size?Math.floor(Math.log(size) / Math.log(1024)):0;
|
||||
// Stay in range of the byte sizes that are defined
|
||||
order = Math.min(humanList.length - 1, order);
|
||||
var readableFormat = humanList[order];
|
||||
|
||||
+29
-25
@@ -66,51 +66,54 @@ var OCdialogs = {
|
||||
/**
|
||||
* prompt user for input with custom form
|
||||
* fields should be passed in following format: [{text:'prompt text', name:'return name', type:'input type', value: 'dafault value'},...]
|
||||
* @param fields to display
|
||||
* select example var fields=[{text:'Test', name:'test', type:'select', options:[{text:'hallo',value:1},{text:'hallo1',value:2}] }];
|
||||
* @param fields to display
|
||||
* @param title dialog title
|
||||
* @param callback which will be triggered when user press OK (user answers will be passed to callback in following format: [{name:'return name', value: 'user value'},...])
|
||||
*/
|
||||
form:function(fields, title, callback, modal) {
|
||||
var content = '<table>';
|
||||
for (var a in fields) {
|
||||
content += '<tr><td>'+fields[a].text+'</td><td>';
|
||||
var type=fields[a].type;
|
||||
$.each(fields, function(index, val){
|
||||
content += '<tr><td>'+val.text+'</td><td>';
|
||||
var type=val.type;
|
||||
|
||||
if (type == 'text' || type == 'checkbox' || type == 'password') {
|
||||
content += '<input type="'+type+'" name="'+fields[a].name+'"';
|
||||
content += '<input type="'+type+'" name="'+val.name+'"';
|
||||
if (type == 'checkbox') {
|
||||
if (fields[a].value != undefined && fields[a].value == true) {
|
||||
if (val.value != undefined && val.value == true) {
|
||||
content += ' checked="checked">';
|
||||
} else {
|
||||
content += '>';
|
||||
}
|
||||
} else if (type == 'text' || type == 'password' && fields[a].value) {
|
||||
content += ' value="'+fields[a].value+'">';
|
||||
} else if (type == 'text' || type == 'password' && val.value) {
|
||||
content += ' value="'+val.value+'">';
|
||||
}
|
||||
} else if (type == 'select') {
|
||||
content += '<select name="'+fields[a].name+'"';
|
||||
if (fields[a].value != undefined) {
|
||||
content += ' value="'+fields[a].value+'"';
|
||||
content += '<select name="'+val.name+'"';
|
||||
if (val.value != undefined) {
|
||||
content += ' value="'+val.value+'"';
|
||||
}
|
||||
content += '>';
|
||||
for (var o in fields[a].options) {
|
||||
content += '<option value="'+fields[a].options[o].value+'">'+fields[a].options[o].text+'</option>';
|
||||
}
|
||||
$.each(val.options, function(index, valo){
|
||||
content += '<option value="'+valo.value+'">'+valo.text+'</option>';
|
||||
});
|
||||
content += '</select>';
|
||||
}
|
||||
content += '</td></tr>';
|
||||
}
|
||||
|
||||
});
|
||||
content += '</table>';
|
||||
OCdialogs.message(content, title, OCdialogs.FORM_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback, modal);
|
||||
},
|
||||
filepicker:function(title, callback, multiselect, mimetype_filter, modal) {
|
||||
var c_name = 'oc-dialog-'+OCdialogs.dialogs_counter+'-content';
|
||||
var c_id = '#'+c_name;
|
||||
var d = '<div id="'+c_name+'" title="'+title+'"><select id="dirtree"><option value="0">'+OC.currentUser+'</option></select><div id="filelist"></div><div class="filepicker_loader"><img src="'+OC.filePath('gallery','img','loading.gif')+'"></div></div>';
|
||||
var d = '<div id="'+c_name+'" title="'+title+'"><select id="dirtree"><option value="0">'+OC.currentUser+'</option></select><div id="filelist"></div><div class="filepicker_loader"><img src="'+OC.filePath('core','img','loading.gif')+'"></div></div>';
|
||||
if (!modal) modal = false; // Huh..
|
||||
if (!multiselect) multiselect = false;
|
||||
$('body').append(d);
|
||||
$(c_id + ' #dirtree').focus(function() {
|
||||
var t = $(this);
|
||||
var t = $(this);
|
||||
t.data('oldval', t.val())
|
||||
}).change({dcid: c_id}, OC.dialogs.handleTreeListSelect);
|
||||
$(c_id).ready(function(){
|
||||
@@ -120,7 +123,7 @@ var OCdialogs = {
|
||||
}).data('multiselect', multiselect).data('mimetype',mimetype_filter);
|
||||
// build buttons
|
||||
var b = [{
|
||||
text: t('core', 'Choose'),
|
||||
text: t('core', 'Choose'),
|
||||
click: function(){
|
||||
if (callback != undefined) {
|
||||
var p;
|
||||
@@ -140,7 +143,7 @@ var OCdialogs = {
|
||||
}
|
||||
},
|
||||
{
|
||||
text: t('core', 'Cancel'),
|
||||
text: t('core', 'Cancel'),
|
||||
click: function(){$(c_id).dialog('close'); }}
|
||||
];
|
||||
$(c_id).dialog({width: ((4*$('body').width())/9), height: 400, modal: modal, buttons: b});
|
||||
@@ -215,9 +218,10 @@ var OCdialogs = {
|
||||
fillFilePicker:function(r, dialog_content_id) {
|
||||
var entry_template = '<div onclick="javascript:OC.dialogs.handlePickerClick(this, \'*ENTRYNAME*\',\''+dialog_content_id+'\')" data="*ENTRYTYPE*"><img src="*MIMETYPEICON*" style="margin-right:1em;"><span id="filename">*NAME*</span><div style="float:right;margin-right:1em;">*LASTMODDATE*</div></div>';
|
||||
var names = '';
|
||||
for (var a in r.data) {
|
||||
names += entry_template.replace('*LASTMODDATE*', OC.mtime2date(r.data[a].mtime)).replace('*NAME*', r.data[a].name).replace('*MIMETYPEICON*', r.data[a].mimetype_icon).replace('*ENTRYNAME*', r.data[a].name).replace('*ENTRYTYPE*', r.data[a].type);
|
||||
}
|
||||
$.each(r.data, function(index, a) {
|
||||
names += entry_template.replace('*LASTMODDATE*', OC.mtime2date(a.mtime)).replace('*NAME*', a.name).replace('*MIMETYPEICON*', a.mimetype_icon).replace('*ENTRYNAME*', a.name).replace('*ENTRYTYPE*', a.type);
|
||||
});
|
||||
|
||||
$(dialog_content_id + ' #filelist').html(names);
|
||||
$(dialog_content_id + ' .filepicker_loader').css('visibility', 'hidden');
|
||||
},
|
||||
@@ -231,10 +235,10 @@ var OCdialogs = {
|
||||
}
|
||||
var skip_first = true;
|
||||
var path = '';
|
||||
$(this).children().each(function(i, element) {
|
||||
$(this).children().each(function(i, element) {
|
||||
if (skip_first) {
|
||||
skip_first = false;
|
||||
return;
|
||||
skip_first = false;
|
||||
return;
|
||||
}
|
||||
path += '/'+$(element).text();
|
||||
});
|
||||
|
||||
+74
-21
@@ -125,7 +125,7 @@ OC.Share={
|
||||
showDropDown:function(itemType, itemSource, appendTo, link, possiblePermissions) {
|
||||
var data = OC.Share.loadItem(itemType, itemSource);
|
||||
var html = '<div id="dropdown" class="drop" data-item-type="'+itemType+'" data-item-source="'+itemSource+'">';
|
||||
if (data.reshare) {
|
||||
if (data !== false && data.reshare !== false && data.reshare.uid_owner !== undefined) {
|
||||
if (data.reshare.share_type == OC.Share.SHARE_TYPE_GROUP) {
|
||||
html += '<span class="reshare">'+t('core', 'Shared with you and the group')+' '+data.reshare.share_with+' '+t('core', 'by')+' '+data.reshare.uid_owner+'</span>';
|
||||
} else {
|
||||
@@ -140,15 +140,19 @@ OC.Share={
|
||||
if (link) {
|
||||
html += '<div id="link">';
|
||||
html += '<input type="checkbox" name="linkCheckbox" id="linkCheckbox" value="1" /><label for="linkCheckbox">'+t('core', 'Share with link')+'</label>';
|
||||
html += '<a href="#" id="showPassword" style="display:none;"><img class="svg" alt="'+t('core', 'Password protect')+'" src="'+OC.imagePath('core', 'actions/lock')+'"/></a>';
|
||||
html += '<br />';
|
||||
html += '<input id="linkText" type="text" readonly="readonly" />';
|
||||
html += '<input type="checkbox" name="showPassword" id="showPassword" value="1" style="display:none;" /><label for="showPassword" style="display:none;">'+t('core', 'Password protect')+'</label>';
|
||||
html += '<div id="linkPass">';
|
||||
html += '<input id="linkPassText" type="password" placeholder="'+t('core', 'Password')+'" />';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
}
|
||||
html += '<div id="expiration">';
|
||||
html += '<form id="emailPrivateLink" >';
|
||||
html += '<input id="email" style="display:none; width:65%;" value="" placeholder="' + t('core', 'Email link to person') + '" type="text" />';
|
||||
html += '<input id="emailButton" style="display:none; float:right;" type="submit" value="' + t('core', 'Send') + '" />';
|
||||
html += '</form>';
|
||||
}
|
||||
html += '<div id="expiration">';
|
||||
html += '<input type="checkbox" name="expirationCheckbox" id="expirationCheckbox" value="1" /><label for="expirationCheckbox">'+t('core', 'Set expiration date')+'</label>';
|
||||
html += '<input id="expirationDate" type="text" placeholder="'+t('core', 'Expiration date')+'" style="display:none; width:90%;" />';
|
||||
html += '</div>';
|
||||
@@ -158,7 +162,7 @@ OC.Share={
|
||||
if (data.shares) {
|
||||
$.each(data.shares, function(index, share) {
|
||||
if (share.share_type == OC.Share.SHARE_TYPE_LINK) {
|
||||
OC.Share.showLink(itemSource, share.share_with);
|
||||
OC.Share.showLink(share.token, share.share_with, itemSource);
|
||||
} else {
|
||||
if (share.collection) {
|
||||
OC.Share.addShareWith(share.share_type, share.share_with, share.permissions, possiblePermissions, share.collection);
|
||||
@@ -302,31 +306,45 @@ OC.Share={
|
||||
$('#expiration').show();
|
||||
}
|
||||
},
|
||||
showLink:function(itemSource, password) {
|
||||
showLink:function(token, password, itemSource) {
|
||||
OC.Share.itemShares[OC.Share.SHARE_TYPE_LINK] = true;
|
||||
$('#linkCheckbox').attr('checked', true);
|
||||
var filename = $('tr').filterAttr('data-id', String(itemSource)).data('file');
|
||||
var type = $('tr').filterAttr('data-id', String(itemSource)).data('type');
|
||||
if ($('#dir').val() == '/') {
|
||||
var file = $('#dir').val() + filename;
|
||||
if (! token) {
|
||||
//fallback to pre token link
|
||||
var filename = $('tr').filterAttr('data-id', String(itemSource)).data('file');
|
||||
var type = $('tr').filterAttr('data-id', String(itemSource)).data('type');
|
||||
if ($('#dir').val() == '/') {
|
||||
var file = $('#dir').val() + filename;
|
||||
} else {
|
||||
var file = $('#dir').val() + '/' + filename;
|
||||
}
|
||||
file = '/'+OC.currentUser+'/files'+file;
|
||||
var link = parent.location.protocol+'//'+location.host+OC.linkTo('', 'public.php')+'?service=files&'+type+'='+encodeURIComponent(file);
|
||||
} else {
|
||||
var file = $('#dir').val() + '/' + filename;
|
||||
//TODO add path param when showing a link to file in a subfolder of a public link share
|
||||
var link = parent.location.protocol+'//'+location.host+OC.linkTo('', 'public.php')+'?service=files&t='+token;
|
||||
}
|
||||
file = '/'+OC.currentUser+'/files'+file;
|
||||
var link = parent.location.protocol+'//'+location.host+OC.linkTo('', 'public.php')+'?service=files&'+type+'='+file;
|
||||
$('#linkText').val(link);
|
||||
$('#linkText').show('blind');
|
||||
$('#linkText').css('display','block');
|
||||
$('#showPassword').show();
|
||||
$('#showPassword+label').show();
|
||||
if (password != null) {
|
||||
$('#linkPass').show('blind');
|
||||
$('#showPassword').attr('checked', true);
|
||||
$('#linkPassText').attr('placeholder', t('core', 'Password protected'));
|
||||
}
|
||||
$('#expiration').show();
|
||||
$('#emailPrivateLink #email').show();
|
||||
$('#emailPrivateLink #emailButton').show();
|
||||
},
|
||||
hideLink:function() {
|
||||
$('#linkText').hide('blind');
|
||||
$('#showPassword').hide();
|
||||
$('#showPassword+label').hide();
|
||||
$('#linkPass').hide();
|
||||
$('#emailPrivateLink #email').hide();
|
||||
$('#emailPrivateLink #emailButton').hide();
|
||||
},
|
||||
dirname:function(path) {
|
||||
return path.replace(/\\/g,'/').replace(/\/[^\/]*$/, '');
|
||||
@@ -339,7 +357,7 @@ OC.Share={
|
||||
$('#expirationDate').datepicker({
|
||||
dateFormat : 'dd-mm-yy'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
@@ -449,8 +467,8 @@ $(document).ready(function() {
|
||||
var itemSource = $('#dropdown').data('item-source');
|
||||
if (this.checked) {
|
||||
// Create a link
|
||||
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', OC.PERMISSION_READ, function() {
|
||||
OC.Share.showLink(itemSource);
|
||||
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', OC.PERMISSION_READ, function(data) {
|
||||
OC.Share.showLink(data.token, null, itemSource);
|
||||
OC.Share.updateIcon(itemType, itemSource);
|
||||
});
|
||||
} else {
|
||||
@@ -473,13 +491,21 @@ $(document).ready(function() {
|
||||
|
||||
$('#showPassword').live('click', function() {
|
||||
$('#linkPass').toggle('blind');
|
||||
});
|
||||
|
||||
$('#linkPassText').live('keyup', function(event) {
|
||||
if (event.keyCode == 13) {
|
||||
if (!$('#showPassword').is(':checked') ) {
|
||||
var itemType = $('#dropdown').data('item-type');
|
||||
var itemSource = $('#dropdown').data('item-source');
|
||||
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, $(this).val(), OC.PERMISSION_READ, function() {
|
||||
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, '', OC.PERMISSION_READ);
|
||||
} else {
|
||||
$('#linkPassText').focus();
|
||||
}
|
||||
});
|
||||
|
||||
$('#linkPassText').live('focusout keyup', function(event) {
|
||||
if ( $('#linkPassText').val() != '' && (event.type == 'focusout' || event.keyCode == 13) ) {
|
||||
var itemType = $('#dropdown').data('item-type');
|
||||
var itemSource = $('#dropdown').data('item-source');
|
||||
OC.Share.share(itemType, itemSource, OC.Share.SHARE_TYPE_LINK, $('#linkPassText').val(), OC.PERMISSION_READ, function() {
|
||||
console.log("password set to: '" + $('#linkPassText').val() +"' by event: " + event.type);
|
||||
$('#linkPassText').val('');
|
||||
$('#linkPassText').attr('placeholder', t('core', 'Password protected'));
|
||||
});
|
||||
@@ -511,4 +537,31 @@ $(document).ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$('#emailPrivateLink').live('submit', function(event) {
|
||||
event.preventDefault();
|
||||
var link = $('#linkText').val();
|
||||
var itemType = $('#dropdown').data('item-type');
|
||||
var itemSource = $('#dropdown').data('item-source');
|
||||
var file = $('tr').filterAttr('data-id', String(itemSource)).data('file');
|
||||
var email = $('#email').val();
|
||||
if (email != '') {
|
||||
$('#email').attr('disabled', "disabled");
|
||||
$('#email').val(t('core', 'Sending ...'));
|
||||
$('#emailButton').attr('disabled', "disabled");
|
||||
|
||||
$.post(OC.filePath('core', 'ajax', 'share.php'), { action: 'email', toaddress: email, link: link, itemType: itemType, itemSource: itemSource, file: file},
|
||||
function(result) {
|
||||
$('#email').attr('disabled', "false");
|
||||
$('#emailButton').attr('disabled', "false");
|
||||
if (result && result.status == 'success') {
|
||||
$('#email').css('font-weight', 'bold');
|
||||
$('#email').animate({ fontWeight: 'normal' }, 2000, function() {
|
||||
$(this).val('');
|
||||
}).val(t('core','Email sent'));
|
||||
} else {
|
||||
OC.dialogs.alert(result.data.message, t('core', 'Error while sharing'));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,8 +13,8 @@ require_once '../../lib/base.php';
|
||||
// Someone lost their password:
|
||||
if (isset($_POST['user'])) {
|
||||
if (OC_User::userExists($_POST['user'])) {
|
||||
$token = hash("sha256", $_POST['user'].OC_Util::generate_random_bytes(10));
|
||||
OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token);
|
||||
$token = hash("sha256", OC_Util::generate_random_bytes(30).OC_Config::getValue('passwordsalt', ''));
|
||||
OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', hash("sha256", $token)); // Hash the token again to prevent timing attacks
|
||||
$email = OC_Preferences::getValue($_POST['user'], 'settings', 'email', '');
|
||||
if (!empty($email)) {
|
||||
$link = OC_Helper::linkToAbsolute('core/lostpassword', 'resetpassword.php', array('user' => $_POST['user'], 'token' => $token));
|
||||
|
||||
@@ -10,7 +10,7 @@ $RUNTIME_NOAPPS = TRUE; //no apps
|
||||
require_once '../../lib/base.php';
|
||||
|
||||
// Someone wants to reset their password:
|
||||
if(isset($_GET['token']) && isset($_GET['user']) && OC_Preferences::getValue($_GET['user'], 'owncloud', 'lostpassword') === $_GET['token']) {
|
||||
if(isset($_GET['token']) && isset($_GET['user']) && OC_Preferences::getValue($_GET['user'], 'owncloud', 'lostpassword') === hash("sha256", $_GET['token'])) {
|
||||
if (isset($_POST['password'])) {
|
||||
if (OC_User::setPassword($_GET['user'], $_POST['password'])) {
|
||||
OC_Preferences::deleteKey($_GET['user'], 'owncloud', 'lostpassword');
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<input type='hidden' id='hasPostgreSQL' value='<?php echo $_['hasPostgreSQL'] ?>'></input>
|
||||
<input type='hidden' id='hasOracle' value='<?php echo $_['hasOracle'] ?>'></input>
|
||||
<form action="index.php" method="post">
|
||||
|
||||
<input type="hidden" name="install" value="true" />
|
||||
<?php if(count($_['errors']) > 0): ?>
|
||||
<ul class="errors">
|
||||
@@ -19,7 +18,20 @@
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if(!$_['secureRNG']): ?>
|
||||
<fieldset style="color: #B94A48; background-color: #F2DEDE; border-color: #EED3D7; border-style:solid; border-radius: 5px; border-width:1px; padding:0.5em;">
|
||||
<legend><strong><?php echo $l->t('Security Warning');?></strong></legend>
|
||||
<span><?php echo $l->t('No secure random number generator is available, please enable the PHP OpenSSL extension.');?></span>
|
||||
<br/>
|
||||
<span><?php echo $l->t('Without a secure random number generator an attacker may be able to predict password reset tokens and take over your account.');?></span>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
<?php if(!$_['htaccessWorking']): ?>
|
||||
<fieldset style="color: #B94A48; background-color: #F2DEDE; border-color: #EED3D7; border-style:solid; border-radius: 5px; border-width:1px; padding:0.5em;">
|
||||
<legend><strong><?php echo $l->t('Security Warning');?></strong></legend>
|
||||
<span><?php echo $l->t('Your data directory and your files are probably accessible from the internet. The .htaccess file that ownCloud provides is not working. We strongly suggest that you configure your webserver in a way that the data directory is no longer accessible or you move the data directory outside the webserver document root.');?></span>
|
||||
</fieldset>
|
||||
<?php endif; ?>
|
||||
<fieldset>
|
||||
<legend><?php echo $l->t( 'Create an <strong>admin account</strong>' ); ?></legend>
|
||||
<p class="infield">
|
||||
@@ -99,7 +111,7 @@
|
||||
</p>
|
||||
<p class="infield">
|
||||
<label for="dbname" class="infield"><?php echo $l->t( 'Database name' ); ?></label>
|
||||
<input type="text" name="dbname" id="dbname" value="<?php print OC_Helper::init_var('dbname'); ?>" autocomplete="off" />
|
||||
<input type="text" name="dbname" id="dbname" value="<?php print OC_Helper::init_var('dbname'); ?>" autocomplete="off" pattern="[0-9a-zA-Z$_]+" />
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -581,6 +581,21 @@
|
||||
<notnull>false</notnull>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<name>token</name>
|
||||
<type>text</type>
|
||||
<default></default>
|
||||
<notnull>false</notnull>
|
||||
<length>32</length>
|
||||
</field>
|
||||
|
||||
<index>
|
||||
<name>token_index</name>
|
||||
<field>
|
||||
<name>token</name>
|
||||
<sorting>ascending</sorting>
|
||||
</field>
|
||||
</index>
|
||||
</declaration>
|
||||
|
||||
</table>
|
||||
|
||||
+7
-7
@@ -117,7 +117,7 @@ msgid ""
|
||||
"strongly suggest that you configure your webserver in a way that the data "
|
||||
"directory is no longer accessible or you move the data directory outside the"
|
||||
" webserver document root."
|
||||
msgstr "Ihr Datenverzeichnis ist möglicher Weise aus dem Internet erreichbar. Die .htaccess-Datei von ownCloud funktioniert nicht. Wir raten Ihnen dringend, dass Sie Ihren Webserver dahingehend konfigurieren, dass Ihr Datenverzeichnis nicht länger aus dem Internet erreichbar ist, oder Sie verschieben das Datenverzeichnis außerhalb des Wurzelverzeichnisses des Webservers."
|
||||
msgstr "Dein Datenverzeichnis ist möglicherweise aus dem Internet erreichbar. Die .htaccess-Datei von ownCloud funktioniert nicht. Wir raten Dir dringend, dass Du Deinen Webserver dahingehend konfigurierst, dass Dein Datenverzeichnis nicht länger aus dem Internet erreichbar ist, oder Du verschiebst das Datenverzeichnis außerhalb des Wurzelverzeichnisses des Webservers."
|
||||
|
||||
#: templates/admin.php:31
|
||||
msgid "Cron"
|
||||
@@ -157,7 +157,7 @@ msgstr "Links erlauben"
|
||||
|
||||
#: templates/admin.php:68
|
||||
msgid "Allow users to share items to the public with links"
|
||||
msgstr "Erlaube Nutzern, Dateien mithilfe von Links öffentlich zu teilen"
|
||||
msgstr "Erlaube Benutzern, Dateien mithilfe von Links öffentlich zu teilen"
|
||||
|
||||
#: templates/admin.php:73
|
||||
msgid "Allow resharing"
|
||||
@@ -165,15 +165,15 @@ msgstr "Erneutes Teilen erlauben"
|
||||
|
||||
#: templates/admin.php:74
|
||||
msgid "Allow users to share items shared with them again"
|
||||
msgstr "Erlaubt Nutzern, Dateien die mit ihnen geteilt wurden, erneut zu teilen"
|
||||
msgstr "Erlaubt Benutzern, Dateien die mit ihnen geteilt wurden, erneut zu teilen"
|
||||
|
||||
#: templates/admin.php:79
|
||||
msgid "Allow users to share with anyone"
|
||||
msgstr "Erlaubet Nutzern mit jedem zu Teilen"
|
||||
msgstr "Erlaube Benutzern, mit jedem zu teilen"
|
||||
|
||||
#: templates/admin.php:81
|
||||
msgid "Allow users to only share with users in their groups"
|
||||
msgstr "Erlaubet Nutzern nur das Teilen in ihrer Gruppe"
|
||||
msgstr "Erlaube Benutzern das Teilen innerhalb ihrer Gruppe"
|
||||
|
||||
#: templates/admin.php:88
|
||||
msgid "Log"
|
||||
@@ -199,7 +199,7 @@ msgstr "Füge Deine Anwendung hinzu"
|
||||
|
||||
#: templates/apps.php:11
|
||||
msgid "More Apps"
|
||||
msgstr ""
|
||||
msgstr "Weitere Apps"
|
||||
|
||||
#: templates/apps.php:27
|
||||
msgid "Select an App"
|
||||
@@ -296,7 +296,7 @@ msgstr "Hilf bei der Übersetzung"
|
||||
|
||||
#: templates/personal.php:51
|
||||
msgid "use this address to connect to your ownCloud in your file manager"
|
||||
msgstr "Benutzen Sie diese Adresse, um Ihre ownCloud mit Ihrem Dateimanager zu verbinden."
|
||||
msgstr "Verwende diese Adresse, um Deine ownCloud mit Deinem Dateimanager zu verbinden."
|
||||
|
||||
#: templates/users.php:21 templates/users.php:76
|
||||
msgid "Name"
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
require_once 'Archive/Tar.php';
|
||||
require_once '3rdparty/Archive/Tar.php';
|
||||
|
||||
class OC_Archive_TAR extends OC_Archive{
|
||||
const PLAIN=0;
|
||||
|
||||
+6
-1
@@ -193,6 +193,7 @@ class OC{
|
||||
public static function checkSSL() {
|
||||
// redirect to https site if configured
|
||||
if( OC_Config::getValue( "forcessl", false )) {
|
||||
header('Strict-Transport-Security: max-age=31536000');
|
||||
ini_set("session.cookie_secure", "on");
|
||||
if(OC_Request::serverProtocol()<>'https' and !OC::$CLI) {
|
||||
$url = "https://". OC_Request::serverHost() . $_SERVER['REQUEST_URI'];
|
||||
@@ -261,6 +262,10 @@ class OC{
|
||||
|
||||
public static function initSession() {
|
||||
ini_set('session.cookie_httponly', '1;');
|
||||
|
||||
// set the session name to the instance id - which is unique
|
||||
session_name(OC_Util::getInstanceId());
|
||||
|
||||
session_start();
|
||||
}
|
||||
|
||||
@@ -281,7 +286,7 @@ class OC{
|
||||
ini_set('arg_separator.output', '&');
|
||||
|
||||
// try to switch magic quotes off.
|
||||
if(function_exists('set_magic_quotes_runtime')) {
|
||||
if(get_magic_quotes_gpc()) {
|
||||
@set_magic_quotes_runtime(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,12 +32,12 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
|
||||
*/
|
||||
protected function validateUserPass($username, $password) {
|
||||
if (OC_User::isLoggedIn()) {
|
||||
OC_Util::setupFS($username);
|
||||
OC_Util::setupFS(OC_User::getUser());
|
||||
return true;
|
||||
} else {
|
||||
OC_Util::setUpFS();//login hooks may need early access to the filesystem
|
||||
if(OC_User::login($username, $password)) {
|
||||
OC_Util::setUpFS($username);
|
||||
OC_Util::setUpFS(OC_User::getUser());
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
@@ -45,4 +45,19 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about the currently logged in username.
|
||||
*
|
||||
* If nobody is currently logged in, this method should return null.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getCurrentUser() {
|
||||
$user = OC_User::getUser();
|
||||
if(!$user) {
|
||||
return null;
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,29 +117,36 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||
*/
|
||||
public function getChildren() {
|
||||
|
||||
$source = $this->getFileSource($this->path);
|
||||
$path = $source['path'];
|
||||
$user = $source['user'];
|
||||
|
||||
$folder_content = OC_Files::getDirectoryContent($this->path);
|
||||
$paths = array();
|
||||
foreach($folder_content as $info) {
|
||||
$paths[] = $this->path.'/'.$info['name'];
|
||||
$paths[] = $path.'/'.$info['name'];
|
||||
}
|
||||
$properties = array_fill_keys($paths, array());
|
||||
if(count($paths)>0) {
|
||||
$placeholders = join(',', array_fill(0, count($paths), '?'));
|
||||
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
|
||||
array_unshift($paths, OC_User::getUser()); // prepend userid
|
||||
$result = $query->execute( $paths );
|
||||
while($row = $result->fetchRow()) {
|
||||
$propertypath = $row['propertypath'];
|
||||
$propertyname = $row['propertyname'];
|
||||
$propertyvalue = $row['propertyvalue'];
|
||||
$properties[$propertypath][$propertyname] = $propertyvalue;
|
||||
$chunks = array_chunk($paths, 200, false);
|
||||
foreach ($chunks as $pack) {
|
||||
$placeholders = join(',', array_fill(0, count($pack), '?'));
|
||||
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ?' . ' AND `propertypath` IN ('.$placeholders.')' );
|
||||
array_unshift($pack, $user); // prepend userid
|
||||
$result = $query->execute( $pack );
|
||||
while($row = $result->fetchRow()) {
|
||||
$propertypath = $row['propertypath'];
|
||||
$propertyname = $row['propertyname'];
|
||||
$propertyvalue = $row['propertyvalue'];
|
||||
$properties[$propertypath][$propertyname] = $propertyvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$nodes = array();
|
||||
foreach($folder_content as $info) {
|
||||
$node = $this->getChild($info['name'], $info);
|
||||
$node->setPropertyCache($properties[$this->path.'/'.$info['name']]);
|
||||
$node->setPropertyCache($properties[$path.'/'.$info['name']]);
|
||||
$nodes[] = $node;
|
||||
}
|
||||
return $nodes;
|
||||
@@ -200,7 +207,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
|
||||
public function getProperties($properties) {
|
||||
$props = parent::getProperties($properties);
|
||||
if (in_array(self::GETETAG_PROPERTYNAME, $properties) && !isset($props[self::GETETAG_PROPERTYNAME])) {
|
||||
$props[self::GETETAG_PROPERTYNAME]
|
||||
$props[self::GETETAG_PROPERTYNAME]
|
||||
= OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
|
||||
}
|
||||
return $props;
|
||||
|
||||
@@ -25,6 +25,13 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
const GETETAG_PROPERTYNAME = '{DAV:}getetag';
|
||||
const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
|
||||
|
||||
/**
|
||||
* Allow configuring the method used to generate Etags
|
||||
*
|
||||
* @var array(class_name, function_name)
|
||||
*/
|
||||
public static $ETagFunction = null;
|
||||
|
||||
/**
|
||||
* The path to the current node
|
||||
*
|
||||
@@ -141,13 +148,16 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
* @return bool|array
|
||||
*/
|
||||
public function updateProperties($properties) {
|
||||
// get source path of shared files
|
||||
$source = self::getFileSource($this->path);
|
||||
|
||||
$existing = $this->getProperties(array());
|
||||
foreach($properties as $propertyName => $propertyValue) {
|
||||
// If it was null, we need to delete the property
|
||||
if (is_null($propertyValue)) {
|
||||
if(array_key_exists( $propertyName, $existing )) {
|
||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName ));
|
||||
$query->execute( array( $source['user'], $source['path'], $propertyName ));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -156,10 +166,10 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
} else {
|
||||
if(!array_key_exists( $propertyName, $existing )) {
|
||||
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
|
||||
$query->execute( array( OC_User::getUser(), $this->path, $propertyName,$propertyValue ));
|
||||
$query->execute( array( $source['user'], $source['path'], $propertyName, $propertyValue ));
|
||||
} else {
|
||||
$query = OC_DB::prepare( 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ? WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?' );
|
||||
$query->execute( array( $propertyValue,OC_User::getUser(), $this->path, $propertyName ));
|
||||
$query->execute( array( $propertyValue, $source['user'], $source['path'], $propertyName ));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,19 +188,22 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
* If the array is empty, all properties should be returned
|
||||
*
|
||||
* @param array $properties
|
||||
* @return void
|
||||
* @return array
|
||||
*/
|
||||
public function getProperties($properties) {
|
||||
if (is_null($this->property_cache)) {
|
||||
|
||||
$source = self::getFileSource($this->path);
|
||||
|
||||
if (is_null($this->property_cache) || empty($this->property_cache)) {
|
||||
$query = OC_DB::prepare( 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?' );
|
||||
$result = $query->execute( array( OC_User::getUser(), $this->path ));
|
||||
$result = $query->execute( array( $source['user'], $source['path'] ));
|
||||
|
||||
$this->property_cache = array();
|
||||
while( $row = $result->fetchRow()) {
|
||||
$this->property_cache[$row['propertyname']] = $row['propertyvalue'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if the array was empty, we need to return everything
|
||||
if(count($properties) == 0) {
|
||||
return $this->property_cache;
|
||||
@@ -209,7 +222,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
* @return string|null Returns null if the ETag can not effectively be determined
|
||||
*/
|
||||
static protected function createETag($path) {
|
||||
return uniqid('', true);
|
||||
if(self::$ETagFunction) {
|
||||
$hash = call_user_func(self::$ETagFunction, $path);
|
||||
return $hash;
|
||||
}else{
|
||||
return uniqid('', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,9 +240,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
if (empty($tag)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$source = self::getFileSource($path);
|
||||
|
||||
$etag = '"'.$tag.'"';
|
||||
$query = OC_DB::prepare( 'INSERT INTO `*PREFIX*properties` (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)' );
|
||||
$query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME, $etag ));
|
||||
$query->execute( array( $source['user'], $source['path'], self::GETETAG_PROPERTYNAME, $etag ));
|
||||
return $etag;
|
||||
}
|
||||
|
||||
@@ -234,6 +255,9 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
*/
|
||||
static public function removeETagPropertyForPath($path) {
|
||||
// remove tags from this and parent paths
|
||||
$source = self::getFileSource($path);
|
||||
$path = $source['path'];
|
||||
|
||||
$paths = array();
|
||||
while ($path != '/' && $path != '.' && $path != '' && $path != '\\') {
|
||||
$paths[] = $path;
|
||||
@@ -249,7 +273,26 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||
.' AND `propertyname` = ?'
|
||||
.' AND `propertypath` IN ('.$path_placeholders.')'
|
||||
);
|
||||
$vals = array( OC_User::getUser(), self::GETETAG_PROPERTYNAME );
|
||||
$vals = array( $source['user'], self::GETETAG_PROPERTYNAME );
|
||||
$query->execute(array_merge( $vals, $paths ));
|
||||
|
||||
//remove etag for all Shared folders
|
||||
$query = OC_DB::prepare( 'DELETE FROM `*PREFIX*properties`'
|
||||
.' WHERE `propertypath` = \'/Shared\' '
|
||||
);
|
||||
$query->execute(array());
|
||||
|
||||
}
|
||||
|
||||
protected static function getFileSource($path) {
|
||||
if ( OC_App::isEnabled('files_sharing') && !strncmp($path, '/Shared/', 8)) {
|
||||
$source = OC_Files_Sharing_Util::getSourcePath(str_replace('/Shared/', '', $path));
|
||||
$parts = explode('/', $source, 4);
|
||||
$user = $parts[1];
|
||||
$path = '/'.$parts[3];
|
||||
} else {
|
||||
$user = OC_User::getUser();
|
||||
}
|
||||
return(array('user' => $user, 'path' => $path));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This plugin check user quota and deny creating files when they exceeds the quota.
|
||||
*
|
||||
* @copyright Copyright (C) 2012 entreCables S.L. All rights reserved.
|
||||
* @author Sergio Cambra
|
||||
* @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
|
||||
*/
|
||||
class OC_Connector_Sabre_QuotaPlugin extends Sabre_DAV_ServerPlugin {
|
||||
|
||||
/**
|
||||
* Reference to main server object
|
||||
*
|
||||
* @var Sabre_DAV_Server
|
||||
*/
|
||||
private $server;
|
||||
|
||||
/**
|
||||
* This initializes the plugin.
|
||||
*
|
||||
* This function is called by Sabre_DAV_Server, after
|
||||
* addPlugin is called.
|
||||
*
|
||||
* This method should set up the requires event subscriptions.
|
||||
*
|
||||
* @param Sabre_DAV_Server $server
|
||||
* @return void
|
||||
*/
|
||||
public function initialize(Sabre_DAV_Server $server) {
|
||||
|
||||
$this->server = $server;
|
||||
$this->server->subscribeEvent('beforeWriteContent', array($this, 'checkQuota'), 10);
|
||||
$this->server->subscribeEvent('beforeCreateFile', array($this, 'checkQuota'), 10);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before any HTTP method and forces users to be authenticated
|
||||
*
|
||||
* @param string $method
|
||||
* @throws Sabre_DAV_Exception
|
||||
* @return bool
|
||||
*/
|
||||
public function checkQuota($uri, $data = null) {
|
||||
$expected = $this->server->httpRequest->getHeader('X-Expected-Entity-Length');
|
||||
$length = $expected ? $expected : $this->server->httpRequest->getHeader('Content-Length');
|
||||
if ($length) {
|
||||
if (substr($uri, 0, 1)!=='/') {
|
||||
$uri='/'.$uri;
|
||||
}
|
||||
list($parentUri, $newName) = Sabre_DAV_URLUtil::splitPath($uri);
|
||||
if ($length > OC_Filesystem::free_space($parentUri)) {
|
||||
throw new Sabre_DAV_Exception_InsufficientStorage();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+6
-11
@@ -168,8 +168,7 @@ class OC_DB {
|
||||
try{
|
||||
self::$PDO=new PDO($dsn, $user, $pass, $opts);
|
||||
}catch(PDOException $e) {
|
||||
echo( '<b>can not connect to database, using '.$type.'. ('.$e->getMessage().')</center>');
|
||||
die();
|
||||
OC_Template::printErrorPage( 'can not connect to database, using '.$type.'. ('.$e->getMessage().')' );
|
||||
}
|
||||
// We always, really always want associative arrays
|
||||
self::$PDO->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
@@ -263,10 +262,7 @@ class OC_DB {
|
||||
|
||||
// Die if we could not connect
|
||||
if( PEAR::isError( self::$MDB2 )) {
|
||||
echo( '<b>can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')</center>');
|
||||
OC_Log::write('core', self::$MDB2->getUserInfo(), OC_Log::FATAL);
|
||||
OC_Log::write('core', self::$MDB2->getMessage(), OC_Log::FATAL);
|
||||
die();
|
||||
OC_Template::printErrorPage( 'can not connect to database, using '.$type.'. ('.self::$MDB2->getUserInfo().')' );
|
||||
}
|
||||
|
||||
// We always, really always want associative arrays
|
||||
@@ -326,7 +322,7 @@ class OC_DB {
|
||||
$entry .= 'Offending command was: '.htmlentities($query).'<br />';
|
||||
OC_Log::write('core', $entry,OC_Log::FATAL);
|
||||
error_log('DB error: '.$entry);
|
||||
die( $entry );
|
||||
OC_Template::printErrorPage( $entry );
|
||||
}
|
||||
}else{
|
||||
try{
|
||||
@@ -336,7 +332,7 @@ class OC_DB {
|
||||
$entry .= 'Offending command was: '.htmlentities($query).'<br />';
|
||||
OC_Log::write('core', $entry,OC_Log::FATAL);
|
||||
error_log('DB error: '.$entry);
|
||||
die( $entry );
|
||||
OC_Template::printErrorPage( $entry );
|
||||
}
|
||||
$result=new PDOStatementWrapper($result);
|
||||
}
|
||||
@@ -449,7 +445,7 @@ class OC_DB {
|
||||
|
||||
// Die in case something went wrong
|
||||
if( $definition instanceof MDB2_Schema_Error ) {
|
||||
die( $definition->getMessage().': '.$definition->getUserInfo());
|
||||
OC_Template::printErrorPage( $definition->getMessage().': '.$definition->getUserInfo() );
|
||||
}
|
||||
if(OC_Config::getValue('dbtype', 'sqlite')==='oci') {
|
||||
unset($definition['charset']); //or MDB2 tries SHUTDOWN IMMEDIATE
|
||||
@@ -461,8 +457,7 @@ class OC_DB {
|
||||
|
||||
// Die in case something went wrong
|
||||
if( $ret instanceof MDB2_Error ) {
|
||||
echo (self::$MDB2->getDebugOutput());
|
||||
die ($ret->getMessage() . ': ' . $ret->getUserInfo());
|
||||
OC_Template::printErrorPage( self::$MDB2->getDebugOutput().' '.$ret->getMessage() . ': ' . $ret->getUserInfo() );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@ class OC_EventSource{
|
||||
private $fallBackId=0;
|
||||
|
||||
public function __construct() {
|
||||
@ob_end_clean();
|
||||
OC_Util::obEnd();
|
||||
header('Cache-Control: no-cache');
|
||||
$this->fallback=isset($_GET['fallback']) and $_GET['fallback']=='true';
|
||||
if($this->fallback) {
|
||||
@@ -80,4 +80,4 @@ class OC_EventSource{
|
||||
public function close() {
|
||||
$this->send('__internal__','close');//server side closing can be an issue, let the client do it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-17
@@ -43,6 +43,9 @@ class OC_FileCache{
|
||||
* - versioned
|
||||
*/
|
||||
public static function get($path,$root=false) {
|
||||
|
||||
list($path, $root) = self::getSourcePathOfSharedFile($path, $root);
|
||||
|
||||
if(OC_FileCache_Update::hasUpdated($path,$root)) {
|
||||
if($root===false) {//filesystem hooks are only valid for the default root
|
||||
OC_Hook::emit('OC_Filesystem','post_write',array('path'=>$path));
|
||||
@@ -65,7 +68,7 @@ class OC_FileCache{
|
||||
if($root===false) {
|
||||
$root=OC_Filesystem::getRoot();
|
||||
}
|
||||
$fullpath=$root.$path;
|
||||
$fullpath=OC_Filesystem::normalizePath($root.'/'.$path);
|
||||
$parent=self::getParentId($fullpath);
|
||||
$id=self::getId($fullpath,'');
|
||||
if(isset(OC_FileCache_Cached::$savedData[$fullpath])) {
|
||||
@@ -79,8 +82,8 @@ class OC_FileCache{
|
||||
|
||||
// add parent directory to the file cache if it does not exist yet.
|
||||
if ($parent == -1 && $fullpath != $root) {
|
||||
$parentDir = substr(dirname($path), 0, strrpos(dirname($path), DIRECTORY_SEPARATOR));
|
||||
self::scanFile($parentDir);
|
||||
$parentDir = dirname(OC_Filesystem::normalizePath($path));
|
||||
self::scanFile($parentDir, $root);
|
||||
$parent = self::getParentId($fullpath);
|
||||
}
|
||||
|
||||
@@ -94,15 +97,19 @@ class OC_FileCache{
|
||||
if(!isset($data['versioned'])) {
|
||||
$data['versioned']=false;
|
||||
}
|
||||
if(!isset($data['user'])) {
|
||||
$data['user']=OC_User::getUser();
|
||||
}
|
||||
|
||||
|
||||
$mimePart=dirname($data['mimetype']);
|
||||
$data['size']=(int)$data['size'];
|
||||
$data['ctime']=(int)$data['mtime'];
|
||||
$data['writable']=(int)$data['writable'];
|
||||
$data['encrypted']=(int)$data['encrypted'];
|
||||
$data['versioned']=(int)$data['versioned'];
|
||||
$user=OC_User::getUser();
|
||||
$query=OC_DB::prepare('INSERT INTO `*PREFIX*fscache`(`parent`, `name`, `path`, `path_hash`, `size`, `mtime`, `ctime`, `mimetype`, `mimepart`,`user`,`writable`,`encrypted`,`versioned`) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
$result=$query->execute(array($parent,basename($fullpath),$fullpath,md5($fullpath),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$user,$data['writable'],$data['encrypted'],$data['versioned']));
|
||||
$result=$query->execute(array($parent,basename($fullpath),$fullpath,md5($fullpath),$data['size'],$data['mtime'],$data['ctime'],$data['mimetype'],$mimePart,$data['user'],$data['writable'],$data['encrypted'],$data['versioned']));
|
||||
if(OC_DB::isError($result)) {
|
||||
OC_Log::write('files','error while writing file('.$fullpath.') to cache',OC_Log::ERROR);
|
||||
}
|
||||
@@ -120,7 +127,7 @@ class OC_FileCache{
|
||||
private static function update($id,$data) {
|
||||
$arguments=array();
|
||||
$queryParts=array();
|
||||
foreach(array('size','mtime','ctime','mimetype','encrypted','versioned','writable') as $attribute) {
|
||||
foreach(array('size','mtime','ctime','mimetype','encrypted','versioned','writable', 'user') as $attribute) {
|
||||
if(isset($data[$attribute])) {
|
||||
//Convert to int it args are false
|
||||
if($data[$attribute] === false) {
|
||||
@@ -203,7 +210,7 @@ class OC_FileCache{
|
||||
|
||||
OC_Cache::remove('fileid/'.$root.$path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return array of filenames matching the querty
|
||||
* @param string $query
|
||||
@@ -273,6 +280,9 @@ class OC_FileCache{
|
||||
* @return int
|
||||
*/
|
||||
public static function getId($path,$root=false) {
|
||||
|
||||
list($path, $root) = self::getSourcePathOfSharedFile($path, $root);
|
||||
|
||||
if($root===false) {
|
||||
$root=OC_Filesystem::getRoot();
|
||||
}
|
||||
@@ -344,21 +354,40 @@ class OC_FileCache{
|
||||
*/
|
||||
public static function increaseSize($path,$sizeDiff, $root=false) {
|
||||
if($sizeDiff==0) return;
|
||||
$id=self::getId($path,$root);
|
||||
if($path =='/'){
|
||||
$path = '';
|
||||
}
|
||||
$item = OC_FileCache_Cached::get($path);
|
||||
//stop walking up the filetree if we hit a non-folder or reached to root folder
|
||||
if($item['mimetype'] !== 'httpd/unix-directory'){
|
||||
return;
|
||||
}
|
||||
$id = $item['id'];
|
||||
while($id!=-1) {//walk up the filetree increasing the size of all parent folders
|
||||
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `size`=`size`+? WHERE `id`=?');
|
||||
$query->execute(array($sizeDiff,$id));
|
||||
$id=self::getParentId($path);
|
||||
$query->execute(array($sizeDiff, $id));
|
||||
if($path ==''){
|
||||
return;
|
||||
}
|
||||
$path=dirname($path);
|
||||
if($path =='/'){
|
||||
$path = '';
|
||||
}
|
||||
$parent = OC_FileCache_Cached::get($path);
|
||||
$id = $parent['id'];
|
||||
//stop walking up the filetree if we hit a non-folder
|
||||
if($parent['mimetype'] !== 'httpd/unix-directory'){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively scan the filesystem and fill the cache
|
||||
* @param string $path
|
||||
* @param OC_EventSource $enventSource (optional)
|
||||
* @param int count (optional)
|
||||
* @param string root (optional)
|
||||
* @param OC_EventSource $eventSource (optional)
|
||||
* @param int $count (optional)
|
||||
* @param string $root (optional)
|
||||
*/
|
||||
public static function scan($path,$eventSource=false,&$count=0,$root=false) {
|
||||
if($eventSource) {
|
||||
@@ -496,16 +525,36 @@ class OC_FileCache{
|
||||
*/
|
||||
public static function triggerUpdate($user=''){
|
||||
if($user) {
|
||||
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`="httpd/unix-directory"');
|
||||
$query->execute(array($user));
|
||||
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `user`=? AND `mimetype`= ? ');
|
||||
$query->execute(array($user,'httpd/unix-directory'));
|
||||
}else{
|
||||
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 AND `mimetype`="httpd/unix-directory"');
|
||||
$query->execute();
|
||||
$query=OC_DB::prepare('UPDATE `*PREFIX*fscache` SET `mtime`=0 WHERE `mimetype`= ? ');
|
||||
$query->execute(array('httpd/unix-directory'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the real path and the root of a shared file
|
||||
* @param string $path
|
||||
* @return array with the path and the root of the give file
|
||||
*/
|
||||
private static function getSourcePathOfSharedFile($path, $root) {
|
||||
if ( OC_App::isEnabled('files_sharing')) {
|
||||
$fullPath = OC_Filesystem::normalizePath($root.'/'.$path);
|
||||
$sharedPos = strpos($fullPath, '/Shared/');
|
||||
if ( $sharedPos !== false && ($source = OC_Files_Sharing_Util::getSourcePath(substr($fullPath, $sharedPos+8))) ) {
|
||||
$parts = explode('/', $source, 4);
|
||||
$root = '/'.$parts[1].'/files';
|
||||
$path = '/'.$parts[3];
|
||||
}
|
||||
}
|
||||
|
||||
return array($path, $root);
|
||||
}
|
||||
}
|
||||
|
||||
//watch for changes and try to keep the cache up to date
|
||||
OC_Hook::connect('OC_Filesystem','post_write','OC_FileCache_Update','fileSystemWatcherWrite');
|
||||
OC_Hook::connect('OC_Filesystem','post_delete','OC_FileCache_Update','fileSystemWatcherDelete');
|
||||
OC_Hook::connect('OC_Filesystem','post_rename','OC_FileCache_Update','fileSystemWatcherRename');
|
||||
OC_Hook::connect('OC_User','post_deleteUser','OC_FileCache_Update','deleteFromUser');
|
||||
|
||||
@@ -18,7 +18,7 @@ class OC_FileCache_Cached{
|
||||
$root=OC_Filesystem::getRoot();
|
||||
}
|
||||
$path=$root.$path;
|
||||
$stmt=OC_DB::prepare('SELECT `path`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `path_hash`=?');
|
||||
$stmt=OC_DB::prepare('SELECT `id`, `path`,`ctime`,`mtime`,`mimetype`,`size`,`encrypted`,`versioned`,`writable` FROM `*PREFIX*fscache` WHERE `path_hash`=?');
|
||||
if ( ! OC_DB::isError($stmt) ) {
|
||||
$result=$stmt->execute(array(md5($path)));
|
||||
if ( ! OC_DB::isError($result) ) {
|
||||
@@ -78,4 +78,4 @@ class OC_FileCache_Cached{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,9 @@ class OC_FileCache_Update{
|
||||
}else{
|
||||
$size=OC_FileCache::scanFile($path, $root);
|
||||
}
|
||||
OC_FileCache::increaseSize(dirname($path), $size-$cachedSize, $root);
|
||||
if($path !== '' and $path !== '/'){
|
||||
OC_FileCache::increaseSize(dirname($path), $size-$cachedSize, $root);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,4 +216,12 @@ class OC_FileCache_Update{
|
||||
OC_FileCache::increaseSize(dirname($newPath), $oldSize, $root);
|
||||
OC_FileCache::move($oldPath, $newPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete files owned by user from the cache
|
||||
* @param string $parameters$parameters["uid"])
|
||||
*/
|
||||
public static function deleteFromUser($parameters) {
|
||||
OC_FileCache::clear($parameters["uid"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Bjoern Schiessle
|
||||
* @copyright 2012 Bjoern Schiessle <schiessle@owncloud.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* check if standard file operations
|
||||
*/
|
||||
|
||||
class OC_FileProxy_FileOperations extends OC_FileProxy{
|
||||
static $rootView;
|
||||
|
||||
public function premkdir($path) {
|
||||
if(!self::$rootView){
|
||||
self::$rootView = new OC_FilesystemView('');
|
||||
}
|
||||
return !self::$rootView->file_exists($path);
|
||||
}
|
||||
|
||||
}
|
||||
+13
-9
@@ -42,16 +42,20 @@ class OC_Files {
|
||||
* - versioned
|
||||
*/
|
||||
public static function getFileInfo($path) {
|
||||
$path = OC_Filesystem::normalizePath($path);
|
||||
if (($path == '/Shared' || substr($path, 0, 8) == '/Shared/') && OC_App::isEnabled('files_sharing')) {
|
||||
if ($path == '/Shared') {
|
||||
list($info) = OCP\Share::getItemsSharedWith('file', OC_Share_Backend_File::FORMAT_FILE_APP_ROOT);
|
||||
}else{
|
||||
$info['size'] = OC_Filesystem::filesize($path);
|
||||
$info['mtime'] = OC_Filesystem::filemtime($path);
|
||||
$info['ctime'] = OC_Filesystem::filectime($path);
|
||||
$info['mimetype'] = OC_Filesystem::getMimeType($path);
|
||||
$info['encrypted'] = false;
|
||||
$info['versioned'] = false;
|
||||
} else {
|
||||
$info = array();
|
||||
if (OC_Filesystem::file_exists($path)) {
|
||||
$info['size'] = OC_Filesystem::filesize($path);
|
||||
$info['mtime'] = OC_Filesystem::filemtime($path);
|
||||
$info['ctime'] = OC_Filesystem::filectime($path);
|
||||
$info['mimetype'] = OC_Filesystem::getMimeType($path);
|
||||
$info['encrypted'] = false;
|
||||
$info['versioned'] = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$info = OC_FileCache::get($path);
|
||||
@@ -161,7 +165,7 @@ class OC_Files {
|
||||
}
|
||||
$zip->close();
|
||||
set_time_limit($executionTime);
|
||||
}elseif(OC_Filesystem::is_dir($dir.'/'.$files)) {
|
||||
}elseif(OC_Filesystem::is_dir(OC_Files::normalizePath($dir.'/'.$files))) {
|
||||
self::validateZipDownload($dir,$files);
|
||||
$executionTime = intval(ini_get('max_execution_time'));
|
||||
set_time_limit(0);
|
||||
@@ -178,7 +182,7 @@ class OC_Files {
|
||||
$zip=false;
|
||||
$filename=$dir.'/'.$files;
|
||||
}
|
||||
@ob_end_clean();
|
||||
OC_Util::obEnd();
|
||||
if($zip or OC_Filesystem::is_readable($filename)) {
|
||||
header('Content-Disposition: attachment; filename="'.basename($filename).'"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
+83
-52
@@ -46,6 +46,7 @@
|
||||
class OC_Filesystem{
|
||||
static private $storages=array();
|
||||
static private $mounts=array();
|
||||
static private $loadedUsers=array();
|
||||
public static $loaded=false;
|
||||
/**
|
||||
* @var OC_Filestorage $defaultInstance
|
||||
@@ -178,72 +179,92 @@ class OC_Filesystem{
|
||||
$internalPath=substr($path,strlen($mountPoint));
|
||||
return $internalPath;
|
||||
}
|
||||
|
||||
static private function mountPointsLoaded($user) {
|
||||
return in_array($user, self::$loadedUsers);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the storage object for a path
|
||||
* @param string path
|
||||
* @return OC_Filestorage
|
||||
*/
|
||||
static public function getStorage($path) {
|
||||
$user = ltrim(substr($path, 0, strpos($path, '/', 1)), '/');
|
||||
// check mount points if file was shared from a different user
|
||||
if ($user != OC_User::getUser() && !self::mountPointsLoaded($user)) {
|
||||
OC_Util::loadUserMountPoints($user);
|
||||
self::loadSystemMountPoints($user);
|
||||
self::$loadedUsers[] = $user;
|
||||
}
|
||||
|
||||
$mountpoint=self::getMountPoint($path);
|
||||
if($mountpoint) {
|
||||
if(!isset(OC_Filesystem::$storages[$mountpoint])) {
|
||||
$mount=OC_Filesystem::$mounts[$mountpoint];
|
||||
OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'],$mount['arguments']);
|
||||
OC_Filesystem::$storages[$mountpoint]=OC_Filesystem::createStorage($mount['class'], $mount['arguments']);
|
||||
}
|
||||
return OC_Filesystem::$storages[$mountpoint];
|
||||
}
|
||||
}
|
||||
|
||||
static public function init($root) {
|
||||
static private function loadSystemMountPoints($user) {
|
||||
if(is_file(OC::$SERVERROOT.'/config/mount.php')) {
|
||||
$mountConfig=include OC::$SERVERROOT.'/config/mount.php';
|
||||
if(isset($mountConfig['global'])) {
|
||||
foreach($mountConfig['global'] as $mountPoint=>$options) {
|
||||
self::mount($options['class'], $options['options'], $mountPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($mountConfig['group'])) {
|
||||
foreach($mountConfig['group'] as $group=>$mounts) {
|
||||
if(OC_Group::inGroup($user, $group)) {
|
||||
foreach($mounts as $mountPoint=>$options) {
|
||||
$mountPoint=self::setUserVars($mountPoint, $user);
|
||||
foreach($options as &$option) {
|
||||
$option=self::setUserVars($option, $user);
|
||||
}
|
||||
self::mount($options['class'], $options['options'], $mountPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($mountConfig['user'])) {
|
||||
foreach($mountConfig['user'] as $mountUser=>$mounts) {
|
||||
if($mountUser==='all' or strtolower($mountUser)===strtolower($user)) {
|
||||
foreach($mounts as $mountPoint=>$options) {
|
||||
$mountPoint=self::setUserVars($mountPoint, $user);
|
||||
foreach($options as &$option) {
|
||||
$option=self::setUserVars($option, $user);
|
||||
}
|
||||
self::mount($options['class'], $options['options'], $mountPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mtime=filemtime(OC::$SERVERROOT.'/config/mount.php');
|
||||
$previousMTime=OC_Appconfig::getValue('files', 'mountconfigmtime', 0);
|
||||
if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated
|
||||
OC_FileCache::triggerUpdate();
|
||||
OC_Appconfig::setValue('files', 'mountconfigmtime', $mtime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function init($root, $user = '') {
|
||||
if(self::$defaultInstance) {
|
||||
return false;
|
||||
}
|
||||
self::$defaultInstance=new OC_FilesystemView($root);
|
||||
|
||||
//load custom mount config
|
||||
if(is_file(OC::$SERVERROOT.'/config/mount.php')) {
|
||||
$mountConfig=include(OC::$SERVERROOT.'/config/mount.php');
|
||||
if(isset($mountConfig['global'])) {
|
||||
foreach($mountConfig['global'] as $mountPoint=>$options) {
|
||||
self::mount($options['class'],$options['options'],$mountPoint);
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($mountConfig['group'])) {
|
||||
foreach($mountConfig['group'] as $group=>$mounts) {
|
||||
if(OC_Group::inGroup(OC_User::getUser(),$group)) {
|
||||
foreach($mounts as $mountPoint=>$options) {
|
||||
$mountPoint=self::setUserVars($mountPoint);
|
||||
foreach($options as &$option) {
|
||||
$option=self::setUserVars($option);
|
||||
}
|
||||
self::mount($options['class'],$options['options'],$mountPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($mountConfig['user'])) {
|
||||
foreach($mountConfig['user'] as $user=>$mounts) {
|
||||
if($user==='all' or strtolower($user)===strtolower(OC_User::getUser())) {
|
||||
foreach($mounts as $mountPoint=>$options) {
|
||||
$mountPoint=self::setUserVars($mountPoint);
|
||||
foreach($options as &$option) {
|
||||
$option=self::setUserVars($option);
|
||||
}
|
||||
self::mount($options['class'],$options['options'],$mountPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mtime=filemtime(OC::$SERVERROOT.'/config/mount.php');
|
||||
$previousMTime=OC_Appconfig::getValue('files','mountconfigmtime',0);
|
||||
if($mtime>$previousMTime) {//mount config has changed, filecache needs to be updated
|
||||
OC_FileCache::triggerUpdate();
|
||||
OC_Appconfig::setValue('files','mountconfigmtime',$mtime);
|
||||
}
|
||||
if (!isset($user)) {
|
||||
$user = OC_User::getUser();
|
||||
}
|
||||
self::loadSystemMountPoints($user);
|
||||
|
||||
self::$loaded=true;
|
||||
}
|
||||
@@ -253,8 +274,12 @@ class OC_Filesystem{
|
||||
* @param string intput
|
||||
* @return string
|
||||
*/
|
||||
private static function setUserVars($input) {
|
||||
return str_replace('$user',OC_User::getUser(),$input);
|
||||
private static function setUserVars($input, $user) {
|
||||
if (isset($user)) {
|
||||
return str_replace('$user', $user,$input);
|
||||
} else {
|
||||
return str_replace('$user',OC_User::getUser(),$input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,12 +396,16 @@ class OC_Filesystem{
|
||||
* @return bool
|
||||
*/
|
||||
static public function isValidPath($path) {
|
||||
$path = self::normalizePath($path);
|
||||
if(!$path || $path[0]!=='/') {
|
||||
$path='/'.$path;
|
||||
}
|
||||
if(strstr($path,'/../') || strrchr($path, '/') === '/..' ) {
|
||||
return false;
|
||||
}
|
||||
if(self::isFileBlacklisted($path)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -386,20 +415,22 @@ class OC_Filesystem{
|
||||
* @param array $data from hook
|
||||
*/
|
||||
static public function isBlacklisted($data) {
|
||||
$blacklist = array('.htaccess');
|
||||
if (isset($data['path'])) {
|
||||
$path = $data['path'];
|
||||
} else if (isset($data['newpath'])) {
|
||||
$path = $data['newpath'];
|
||||
}
|
||||
if (isset($path)) {
|
||||
$filename = strtolower(basename($path));
|
||||
if (in_array($filename, $blacklist)) {
|
||||
$data['run'] = false;
|
||||
}
|
||||
$data['run'] = !self::isFileBlacklisted($path);
|
||||
}
|
||||
}
|
||||
|
||||
static public function isFileBlacklisted($path){
|
||||
$blacklist = array('.htaccess');
|
||||
$filename = strtolower(basename($path));
|
||||
return in_array($filename, $blacklist);
|
||||
}
|
||||
|
||||
/**
|
||||
* following functions are equivilent to their php buildin equivilents for arguments/return values.
|
||||
*/
|
||||
@@ -531,7 +562,7 @@ class OC_Filesystem{
|
||||
if ($root) { // reduce path to the required part of it (no 'username/files')
|
||||
$fakeRootView = new OC_FilesystemView($root);
|
||||
$count = 1;
|
||||
$path=str_replace(OC_App::getStorage("files")->getAbsolutePath($path), "", $fakeRootView->getAbsolutePath($path), $count);
|
||||
$path=str_replace(OC_App::getStorage("files")->getAbsolutePath(), "", $fakeRootView->getAbsolutePath($path), $count);
|
||||
}
|
||||
|
||||
$path = self::normalizePath($path);
|
||||
|
||||
+30
-8
@@ -47,11 +47,8 @@ class OC_FilesystemView {
|
||||
$this->fakeRoot=$root;
|
||||
}
|
||||
|
||||
public function getAbsolutePath($path) {
|
||||
if(!$path) {
|
||||
$path='/';
|
||||
}
|
||||
if($path[0]!=='/') {
|
||||
public function getAbsolutePath($path = '/') {
|
||||
if(!$path || $path[0]!=='/') {
|
||||
$path='/'.$path;
|
||||
}
|
||||
return $this->fakeRoot.$path;
|
||||
@@ -198,7 +195,7 @@ class OC_FilesystemView {
|
||||
return $this->basicOperation('filesize', $path);
|
||||
}
|
||||
public function readfile($path) {
|
||||
@ob_end_clean();
|
||||
OC_Util::obEnd();
|
||||
$handle=$this->fopen($path, 'rb');
|
||||
if ($handle) {
|
||||
$chunkSize = 8192;// 8 MB chunks
|
||||
@@ -251,6 +248,9 @@ class OC_FilesystemView {
|
||||
return $this->basicOperation('filemtime', $path);
|
||||
}
|
||||
public function touch($path, $mtime=null) {
|
||||
if(!is_null($mtime) and !is_numeric($mtime)){
|
||||
$mtime = strtotime($mtime);
|
||||
}
|
||||
return $this->basicOperation('touch', $path, array('write'), $mtime);
|
||||
}
|
||||
public function file_get_contents($path) {
|
||||
@@ -431,6 +431,9 @@ class OC_FilesystemView {
|
||||
$result = OC_Helper::streamCopy($source, $target);
|
||||
}
|
||||
if( $this->fakeRoot==OC_Filesystem::getRoot() ){
|
||||
// If the file to be copied originates within
|
||||
// the user's data directory
|
||||
|
||||
OC_Hook::emit(
|
||||
OC_Filesystem::CLASSNAME,
|
||||
OC_Filesystem::signal_post_copy,
|
||||
@@ -451,9 +454,28 @@ class OC_FilesystemView {
|
||||
OC_Filesystem::signal_post_write,
|
||||
array( OC_Filesystem::signal_param_path => $path2)
|
||||
);
|
||||
} else { // no real copy, file comes from somewhere else, e.g. version rollback -> just update the file cache and the webdav properties without all the other post_write actions
|
||||
OC_FileCache_Update::update($path2, $this->fakeRoot);
|
||||
} else {
|
||||
// If this is not a normal file copy operation
|
||||
// and the file originates somewhere else
|
||||
// (e.g. a version rollback operation), do not
|
||||
// perform all the other post_write actions
|
||||
|
||||
// Update webdav properties
|
||||
OC_Filesystem::removeETagHook(array("path" => $path2), $this->fakeRoot);
|
||||
|
||||
$splitPath2 = explode( '/', $path2 );
|
||||
|
||||
// Only cache information about files
|
||||
// that are being copied from within
|
||||
// the user files directory. Caching
|
||||
// other files, like VCS backup files,
|
||||
// serves no purpose
|
||||
if ( $splitPath2[1] == 'files' ) {
|
||||
|
||||
OC_FileCache_Update::update($path2, $this->fakeRoot);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user