From 7ed8f3974417964df18b135b154fdfdbd4f1b6ca Mon Sep 17 00:00:00 2001 From: Nils Jansen Date: Fri, 23 Mar 2012 13:34:07 +0100 Subject: [PATCH 01/37] as preperation for the sgf viewer app i added a file icon for .sgf files (saved go games), and an according mimetype. --- core/img/filetypes/application-sgf.png | Bin 0 -> 725 bytes lib/mimetypes.fixlist.php | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 core/img/filetypes/application-sgf.png diff --git a/core/img/filetypes/application-sgf.png b/core/img/filetypes/application-sgf.png new file mode 100644 index 0000000000000000000000000000000000000000..f171f5579e735fe5cc729144e059263a0bc20741 GIT binary patch literal 725 zcmV;`0xJE9P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyY| z5)UXgb;nEq00LD>L_t(2&y`Y3NK|1M{r<;&%|*p1(?-!0dSaM?nHfsC5sVfsOl)03 zZCV9E(8fiyx1e2%+GJ1=Cgn~ggT$~@vMH)@Y@8Wq#&O1b@BjE(jH$Kj>^?Y$^Ks50 zhzS1!zVjF!x;#C<8u^)9imwsS6}zkhwWV!Ml|5G;Z*fS`;p5og$k_YwnN%X}NvQ)N zf*|mHPsyOJDs(97r9Q_~884OHpv;m|Nh(1jAd>CmP-~4E0pR;mb|tpRmlNyxf^S)bF~(6N z>YYJrt(8(rD@4rYgIGMrtM<5zDBt%10EAHbUx5%pDW$b8FSTp-mGbfu)3xbJ+EYp) z=f2Vb0r=Ctuapo%N(lgU;j(bUDT0WX&Nq)w|00xe#;SqXh)O9bm6Rgpd9lEgQiW{e zTK|c=4<|VQoNWnzT1+e_3WUJ6)t{ZY) zHxvrlwqqCuW0VlW7;QXQF?6T9$lM%X-^DJ|pu?jJU!xfzl-3#%DJ3PYdHhIaU(eC2 zw_pA>z9L>c=$)L7&P9?xVp-edwc)a+!+YDBt2_E1ZE=1B;p|h!+58Bn00000NkvXX Hu0mjfh3`Xt literal 0 HcmV?d00001 diff --git a/lib/mimetypes.fixlist.php b/lib/mimetypes.fixlist.php index 51f12dbcc2..a40fbd9e22 100644 --- a/lib/mimetypes.fixlist.php +++ b/lib/mimetypes.fixlist.php @@ -16,5 +16,6 @@ return array( 'xls'=>'application/msexcel', 'xlsx'=>'application/msexcel', 'ppt'=>'application/mspowerpoint', - 'pptx'=>'application/mspowerpoint' + 'pptx'=>'application/mspowerpoint', + 'sgf' => 'application/sgf' ); From bcda46eda3b3b9208609bc5a9497632aa0dabfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20H=C3=BClsmann?= Date: Wed, 28 Mar 2012 16:07:50 +0200 Subject: [PATCH 02/37] webfinger installation creates symlink in document root --- apps/user_webfinger/appinfo/install.php | 32 ++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/user_webfinger/appinfo/install.php b/apps/user_webfinger/appinfo/install.php index f570a3a249..9ba953a4e6 100644 --- a/apps/user_webfinger/appinfo/install.php +++ b/apps/user_webfinger/appinfo/install.php @@ -3,4 +3,34 @@ $appInfoDir = __DIR__; $thisAppDir = dirname($appInfoDir); $appsDir = dirname($thisAppDir); $ownCloudDir = dirname($appsDir); -@symlink($thisAppDir, $ownCloudDir.'/.well-known'); +$docRoot = $_SERVER['DOCUMENT_ROOT']; +if(file_exists($docRoot . '/.well-known/host-meta')) { + OC_Log::write( + 'user_webfinger', + $docRoot . "/.well-known already exists; installation aborted", + OC_Log::ERROR + ); +} else { + if(@symlink($thisAppDir, $docRoot . '/.well-known')) { + OC_Log::write( + 'user_webfinger', + "Webfinger symlink created at " . $docRoot . "/.well-known", + OC_Log::INFO + ); + } else { + if(@symlink($thisAppDir, $ownCloudDir . '/.well-known')) { + OC_Log::write( + 'user_webfinger', + "Couldn't create webfinger symlink in document root, linked to " . $ownCloudDir . "/.well-known instead", + OC_Log::WARN + ); + } else { + OC_Log::write( + 'user_webfinger', + "Couldn't create webfinger symlink, either check write permissions or create the link manually!", + OC_Log::ERROR + ); + } + } +} +?> From 34a0128ddf01a44302f89a1dfa14bb9565a8ae47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20H=C3=BClsmann?= Date: Wed, 28 Mar 2012 16:12:34 +0200 Subject: [PATCH 03/37] whitespace indentation fix --- apps/user_webfinger/appinfo/install.php | 52 ++++++++++++------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/apps/user_webfinger/appinfo/install.php b/apps/user_webfinger/appinfo/install.php index 9ba953a4e6..775141dce4 100644 --- a/apps/user_webfinger/appinfo/install.php +++ b/apps/user_webfinger/appinfo/install.php @@ -5,32 +5,32 @@ $appsDir = dirname($thisAppDir); $ownCloudDir = dirname($appsDir); $docRoot = $_SERVER['DOCUMENT_ROOT']; if(file_exists($docRoot . '/.well-known/host-meta')) { - OC_Log::write( - 'user_webfinger', - $docRoot . "/.well-known already exists; installation aborted", - OC_Log::ERROR - ); + OC_Log::write( + 'user_webfinger', + $docRoot . "/.well-known already exists; installation aborted", + OC_Log::ERROR + ); } else { - if(@symlink($thisAppDir, $docRoot . '/.well-known')) { - OC_Log::write( - 'user_webfinger', - "Webfinger symlink created at " . $docRoot . "/.well-known", - OC_Log::INFO - ); - } else { - if(@symlink($thisAppDir, $ownCloudDir . '/.well-known')) { - OC_Log::write( - 'user_webfinger', - "Couldn't create webfinger symlink in document root, linked to " . $ownCloudDir . "/.well-known instead", - OC_Log::WARN - ); - } else { - OC_Log::write( - 'user_webfinger', - "Couldn't create webfinger symlink, either check write permissions or create the link manually!", - OC_Log::ERROR - ); - } - } + if(@symlink($thisAppDir, $docRoot . '/.well-known')) { + OC_Log::write( + 'user_webfinger', + "Webfinger symlink created at " . $docRoot . "/.well-known", + OC_Log::INFO + ); + } else { + if(@symlink($thisAppDir, $ownCloudDir . '/.well-known')) { + OC_Log::write( + 'user_webfinger', + "Couldn't create webfinger symlink in document root, linked to " . $ownCloudDir . "/.well-known instead", + OC_Log::WARN + ); + } else { + OC_Log::write( + 'user_webfinger', + "Couldn't create webfinger symlink, either check write permissions or create the link manually!", + OC_Log::ERROR + ); + } + } } ?> From 5161758921efb5bb50e579d8e6debfa93e595a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20H=C3=BClsmann?= Date: Fri, 30 Mar 2012 21:35:09 +0200 Subject: [PATCH 04/37] create static host-meta instead of symlink and .htaccess --- apps/user_webfinger/appinfo/install.php | 57 ++++++++++++------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/apps/user_webfinger/appinfo/install.php b/apps/user_webfinger/appinfo/install.php index 775141dce4..678d57ae8f 100644 --- a/apps/user_webfinger/appinfo/install.php +++ b/apps/user_webfinger/appinfo/install.php @@ -4,33 +4,32 @@ $thisAppDir = dirname($appInfoDir); $appsDir = dirname($thisAppDir); $ownCloudDir = dirname($appsDir); $docRoot = $_SERVER['DOCUMENT_ROOT']; -if(file_exists($docRoot . '/.well-known/host-meta')) { - OC_Log::write( - 'user_webfinger', - $docRoot . "/.well-known already exists; installation aborted", - OC_Log::ERROR - ); -} else { - if(@symlink($thisAppDir, $docRoot . '/.well-known')) { - OC_Log::write( - 'user_webfinger', - "Webfinger symlink created at " . $docRoot . "/.well-known", - OC_Log::INFO - ); - } else { - if(@symlink($thisAppDir, $ownCloudDir . '/.well-known')) { - OC_Log::write( - 'user_webfinger', - "Couldn't create webfinger symlink in document root, linked to " . $ownCloudDir . "/.well-known instead", - OC_Log::WARN - ); - } else { - OC_Log::write( - 'user_webfinger', - "Couldn't create webfinger symlink, either check write permissions or create the link manually!", - OC_Log::ERROR - ); - } - } +try { + $webRoot = substr(realpath($ownCloudDir), strlen(realpath($docRoot))); +} catch(Exception $e) { + // some servers fail on realpath(), let's try it the unsecure way: + $webRoot = substr($ownCloudDir, strlen($docRoot)); } -?> +$serverName = $_SERVER['SERVER_NAME']; +$lrddTmpl = 'http'; +if(isset($_SERVER['HTTPS'])) { + $lrddTmpl .= 's'; +} +$lrddTmpl .= '://' . $serverName . $webRoot . '/apps/user_webfinger/webfinger.php?q={uri}'; +$hostMetaPath = $docRoot . '/.well-known/host-meta'; +$hostMetaContents = " + + " . $serverName . " + + Resource Descriptor + +"; +@mkdir(dirname($hostMetaPath)); +$hostMeta = fopen($hostMetaPath, 'w'); +if(!$hostMeta) { + die("Could not open " . $hostMetaPath . " for writing, please check permissions!"); +} +if(!fwrite($hostMeta, $hostMetaContents, strlen($hostMetaContents))) { + die("Could not write to " . $hostMetaPath . ", please check permissions!"); +} +fclose($hostMeta); From f9f91a08b47c0a086c43966b1ecdf87185ceef83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20H=C3=BClsmann?= Date: Sat, 31 Mar 2012 02:42:41 +0200 Subject: [PATCH 05/37] webfinger reimplementation started --- apps/remoteStorage/appinfo/info.xml | 2 +- apps/remoteStorage/appinfo/webfinger.php | 6 +++ apps/user_webfinger/.htaccess | 3 -- apps/user_webfinger/appinfo/info.xml | 6 +-- apps/user_webfinger/host-meta | 1 - apps/user_webfinger/host-meta.php | 16 ------- apps/user_webfinger/webfinger.php | 57 +++++++++++++++++------- 7 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 apps/remoteStorage/appinfo/webfinger.php delete mode 100644 apps/user_webfinger/.htaccess delete mode 100644 apps/user_webfinger/host-meta delete mode 100644 apps/user_webfinger/host-meta.php diff --git a/apps/remoteStorage/appinfo/info.xml b/apps/remoteStorage/appinfo/info.xml index 121587795d..1ab55e8c09 100644 --- a/apps/remoteStorage/appinfo/info.xml +++ b/apps/remoteStorage/appinfo/info.xml @@ -3,7 +3,7 @@ remoteStorage remoteStorage compatibility Enables your users to use ownCloud as their remote storage for unhosted applications. - 0.5 + 0.6 AGPL or MIT Michiel de Jong 2 diff --git a/apps/remoteStorage/appinfo/webfinger.php b/apps/remoteStorage/appinfo/webfinger.php new file mode 100644 index 0000000000..bb3fe1681b --- /dev/null +++ b/apps/remoteStorage/appinfo/webfinger.php @@ -0,0 +1,6 @@ + + diff --git a/apps/user_webfinger/.htaccess b/apps/user_webfinger/.htaccess deleted file mode 100644 index 4d4d2e9c58..0000000000 --- a/apps/user_webfinger/.htaccess +++ /dev/null @@ -1,3 +0,0 @@ -RewriteEngine On -RewriteBase / -RewriteRule host-meta$ \/\.well-known\/host-meta\.php [L] diff --git a/apps/user_webfinger/appinfo/info.xml b/apps/user_webfinger/appinfo/info.xml index 55cf2cf220..d47fb723a3 100644 --- a/apps/user_webfinger/appinfo/info.xml +++ b/apps/user_webfinger/appinfo/info.xml @@ -2,9 +2,9 @@ user_webfinger Webfinger - Provide WebFinger for all users so they get a user address like user@owncloudinstance which can be used for unhosted applications. If you don't run ownCloud in the root of your domain, for instance if you run it on example.com/owncloud/, then make sure you link example.com/.well-known/ to example.com/owncloud/apps/user_webfinger/ - by running something like "ln -s /var/www/owncloud/apps/user_webfinger /var/www/.well-known". Only enable this app if you run this ownCloud installation on a public web address, not if you run it on an intranet or on localhost. - 0.2 + Provide WebFinger for all users so they get a user address like user@owncloudinstance which can be used for external applications. Other apps can provide information for webfinger requests, such as remoteStorage compatibility. + 0.3 AGPL or MIT - Michiel de Jong + Michiel de Jong, Florian Hülsmann 2 diff --git a/apps/user_webfinger/host-meta b/apps/user_webfinger/host-meta deleted file mode 100644 index dfaf363614..0000000000 --- a/apps/user_webfinger/host-meta +++ /dev/null @@ -1 +0,0 @@ -please run 'a2enmod rewrite' on your server, set 'AllowOverride All' for /var/www in /etc/apache2/sites-enabled/000-default or equivalent, and then run '/etc/init.d/apache2 restart' diff --git a/apps/user_webfinger/host-meta.php b/apps/user_webfinger/host-meta.php deleted file mode 100644 index ac577cf9a0..0000000000 --- a/apps/user_webfinger/host-meta.php +++ /dev/null @@ -1,16 +0,0 @@ - -?xml version="1.0" encoding="UTF-8"?> - - - - - - diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php index 5c2a24aa07..ecbfeed8e4 100644 --- a/apps/user_webfinger/webfinger.php +++ b/apps/user_webfinger/webfinger.php @@ -1,41 +1,68 @@ /apps/myApp/profile.php?user="> + * + * + '* but can also use complex database queries to generate the webfinger result + **/ // calculate the documentroot // modified version of the one in lib/base.php that takes the .well-known symlink into account -$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']); +/*$DOCUMENTROOT=realpath($_SERVER['DOCUMENT_ROOT']); $SERVERROOT=str_replace("\\",'/',dirname(dirname(dirname(dirname(__FILE__))))); $SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen($SERVERROOT)); $WEBROOT=substr($SUBURI,0,-34); +*/ +require_once('../../lib/base.php'); +$id = $_GET['q']; if($_GET['q']) { $bits = explode('@', $_GET['q']); $userName = $bits[0]; } else { + $id = ''; $userName = ''; } if(substr($userName, 0, 5) == 'acct:') { $userName = substr($userName, 5); } if(isset($_SERVER['HTTPS'])) { - $baseAddress = 'https://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/'; + $baseAddress = 'https://'; } else { - $baseAddress = 'http://'.$_SERVER['SERVER_NAME'].'/apps/remoteStorage/'; + $baseAddress = 'http://'; } +$baseAddress .= $_SERVER['SERVER_NAME'].OC::$WEBROOT; +define('WF_USER', $userName); +define('WF_ADDRESS', $id); +define('WF_ROOT', $baseAddress); echo "<"; ?> ?xml version="1.0" encoding="UTF-8"?> - - + + acct: + From 6bb48b2731185dd93ad1a1edc52f33725cd99061 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 1 Apr 2012 02:38:26 -0400 Subject: [PATCH 06/37] Check file handle exists before trying to read file --- lib/filesystemview.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/filesystemview.php b/lib/filesystemview.php index 39e47975b2..a3736f1976 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -137,13 +137,16 @@ class OC_FilesystemView { } public function readfile($path){ $handle=$this->fopen($path,'r'); - $chunkSize = 1024*1024;// 1 MB chunks - while (!feof($handle)) { - echo fread($handle, $chunkSize); - @ob_flush(); - flush(); + if ($handle) { + $chunkSize = 1024*1024;// 1 MB chunks + while (!feof($handle)) { + echo fread($handle, $chunkSize); + @ob_flush(); + flush(); + } + return $this->filesize($path); } - return $this->filesize($path); + return false; } public function is_readable($path){ return $this->basicOperation('is_readable',$path); From 6545e4878715c10d85a72b1cdb3f7cef73d7e383 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Sun, 1 Apr 2012 11:20:12 +0200 Subject: [PATCH 07/37] Show the different editions to the user. Used in the status call, on the personal settings page and in the updater to update to the next available version from the same edition. --- lib/updater.php | 1 + lib/util.php | 8 ++++++++ settings/templates/personal.php | 2 +- status.php | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/updater.php b/lib/updater.php index 57623797ae..196822ac35 100644 --- a/lib/updater.php +++ b/lib/updater.php @@ -36,6 +36,7 @@ class OC_Updater{ $version['installed']=OC_Config::getValue('installedat'); $version['updated']=OC_Appconfig::getValue('core', 'lastupdatedat', OC_Config::getValue( 'lastupdatedat')); $version['updatechannel']='stable'; + $version['edition']=OC_Util::getEditionString(); $versionstring=implode('x',$version); //fetch xml data from updater diff --git a/lib/util.php b/lib/util.php index 529b6d958f..722b7404d0 100644 --- a/lib/util.php +++ b/lib/util.php @@ -77,6 +77,14 @@ class OC_Util { return '3'; } + /** + * get the current installed edition of ownCloud. There is the community edition that just returns an empty string and the enterprise edition that returns "Enterprise". + * @return string + */ + public static function getEditionString(){ + return ''; + } + /** * add a javascript file * diff --git a/settings/templates/personal.php b/settings/templates/personal.php index 57731d979d..d40da7eb77 100644 --- a/settings/templates/personal.php +++ b/settings/templates/personal.php @@ -50,7 +50,7 @@ };?>

- ownCloud
+ ownCloud
developed by the ownCloud community

source code licensed freely under AGPL diff --git a/status.php b/status.php index 94c8cfce84..81f339fa53 100644 --- a/status.php +++ b/status.php @@ -26,7 +26,7 @@ $RUNTIME_NOAPPS = TRUE; //no apps, yet require_once('lib/base.php'); if(OC_Config::getValue('installed')==1) $installed='true'; else $installed='false'; -$values=array('installed'=>$installed,'version'=>implode('.',OC_Util::getVersion()),'versionstring'=>OC_Util::getVersionString()); +$values=array('installed'=>$installed,'version'=>implode('.',OC_Util::getVersion()),'versionstring'=>OC_Util::getVersionString(),'edition'=>OC_Util::getEditionString()); echo(json_encode($values)); From 1b8a644c31a83279e9829aac74fbbc843d49f65d Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Sun, 1 Apr 2012 16:06:08 +0200 Subject: [PATCH 08/37] update outdated README --- README | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README b/README index 4d4be2728e..77379a4645 100644 --- a/README +++ b/README @@ -3,10 +3,11 @@ A personal cloud which runs on your own server. http://ownCloud.org -Installation instructions: http://owncloud.org/support/setup-and-installation/ -Source code: http://gitorious.org/owncloud +Installation instructions: http://owncloud.org/support +Source code: http://gitorious.org/owncloud Mailing list: http://mail.kde.org/mailman/listinfo/owncloud IRC channel: http://webchat.freenode.net/?channels=owncloud Diaspora: https://joindiaspora.com/u/owncloud Identi.ca: http://identi.ca/owncloud + From b758725bf7fad960e971adfeb826596e02673244 Mon Sep 17 00:00:00 2001 From: Frank Karlitschek Date: Sun, 1 Apr 2012 17:02:32 +0200 Subject: [PATCH 09/37] =?UTF-8?q?Try=20to=20configure=20php=20to=20enable?= =?UTF-8?q?=20big=20file=20uploads.=20This=20doesn=C2=B4t=20work=20always?= =?UTF-8?q?=20depending=20on=20the=20webserver=20and=20php=20configuration?= =?UTF-8?q?.=20Let=C2=B4s=20try=20to=20overwrite=20some=20defaults=20anywa?= =?UTF-8?q?ys?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/base.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/base.php b/lib/base.php index 22f7f4ea48..a4a94e8696 100644 --- a/lib/base.php +++ b/lib/base.php @@ -277,6 +277,24 @@ class OC{ date_default_timezone_set('Europe/Berlin'); ini_set('arg_separator.output','&'); + //try to configure php to enable big file uploads. + //this doesn´t work always depending on the webserver and php configuration. + //Let´s try to overwrite some defaults anyways + + //try to set the maximum execution time to 60min + @set_time_limit(3600); + @ini_set('max_execution_time',3600); + @ini_set('max_input_time',3600); + + //try to set the maximum filesize to 10G + @ini_set('upload_max_filesize','10G'); + @ini_set('post_max_size','10G'); + @ini_set('file_uploads','50'); + + //try to set the session lifetime to 60min + @ini_set('gc_maxlifetime','3600'); + + //set http auth headers for apache+php-cgi work around if (isset($_SERVER['HTTP_AUTHORIZATION']) && preg_match('/Basic\s+(.*)$/i', $_SERVER['HTTP_AUTHORIZATION'], $matches)) { From 39e8981bc2ef098a020476a9d94a4b0cc4d9e1c9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 1 Apr 2012 17:31:44 +0200 Subject: [PATCH 10/37] oc_db is not pdo also pgsql does not like double quotes --- lib/app.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/app.php b/lib/app.php index 6c882963a0..625ef88967 100755 --- a/lib/app.php +++ b/lib/app.php @@ -103,9 +103,9 @@ class OC_App{ */ public static function getEnabledApps(){ $apps=array(); - $query = OC_DB::prepare( 'SELECT appid FROM *PREFIX*appconfig WHERE configkey = "enabled" AND configvalue="yes"' ); - $query->execute(); - while($row=$query->fetchRow()){ + $query = OC_DB::prepare( 'SELECT appid FROM *PREFIX*appconfig WHERE configkey = \'enabled\' AND configvalue=\'yes\'' ); + $result=$query->execute(); + while($row=$result->fetchRow()){ $apps[]=$row['appid']; } return $apps; @@ -452,7 +452,7 @@ class OC_App{ */ public static function getAppVersions(){ $versions=array(); - $query = OC_DB::prepare( 'SELECT appid, configvalue FROM *PREFIX*appconfig WHERE configkey = "installed_version"' ); + $query = OC_DB::prepare( 'SELECT appid, configvalue FROM *PREFIX*appconfig WHERE configkey = \'installed_version\'' ); $result = $query->execute(); while($row = $result->fetchRow()){ $versions[$row['appid']]=$row['configvalue']; From cce59df2ae399bc43f1c11a3162b4855de70a1bc Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 1 Apr 2012 19:20:59 +0200 Subject: [PATCH 11/37] the core apps don't have types --- lib/app.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/app.php b/lib/app.php index 625ef88967..7d5e8fa91c 100755 --- a/lib/app.php +++ b/lib/app.php @@ -55,7 +55,7 @@ class OC_App{ // Our very own core apps are hardcoded foreach( array('files', 'settings') as $app ){ - if(is_null($types) or self::isType($app,$types)){ + if(is_null($types)){ require( $app.'/appinfo/app.php' ); } } From ff4b0c4d7f6b422c9426205897c015b497429b03 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sun, 1 Apr 2012 13:30:41 -0400 Subject: [PATCH 12/37] Move writable check into local filestorage so shared files can be renamed --- lib/filestorage/local.php | 4 ++++ lib/filesystemview.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/filestorage/local.php b/lib/filestorage/local.php index 688501aee9..bd757f52ce 100644 --- a/lib/filestorage/local.php +++ b/lib/filestorage/local.php @@ -86,6 +86,10 @@ class OC_Filestorage_Local extends OC_Filestorage{ return $this->delTree($path); } public function rename($path1,$path2){ + if (!$this->is_writable($path1)) { + OC_Log::write('core','unable to rename, file is not writable : '.$path1,OC_Log::ERROR); + return false; + } if(! $this->file_exists($path1)){ OC_Log::write('core','unable to rename, file does not exists : '.$path1,OC_Log::ERROR); return false; diff --git a/lib/filesystemview.php b/lib/filesystemview.php index a3736f1976..9d530c7ad6 100644 --- a/lib/filesystemview.php +++ b/lib/filesystemview.php @@ -192,7 +192,7 @@ class OC_FilesystemView { return $this->basicOperation('unlink',$path,array('delete')); } public function rename($path1,$path2){ - if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and $this->is_writable($path1) and OC_Filesystem::isValidPath($path2)){ + if(OC_FileProxy::runPreProxies('rename',$path1,$path2) and OC_Filesystem::isValidPath($path2)){ $run=true; OC_Hook::emit( OC_Filesystem::CLASSNAME, OC_Filesystem::signal_rename, array( OC_Filesystem::signal_param_oldpath => $path1 , OC_Filesystem::signal_param_newpath=>$path2, OC_Filesystem::signal_param_run => &$run)); if($run){ From 3e150ff548a8bf3b29729ab9b04a1f38538737f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20H=C3=BClsmann?= Date: Mon, 2 Apr 2012 06:31:00 +0200 Subject: [PATCH 13/37] webfinger protocol compatible + minor changes --- apps/remoteStorage/appinfo/webfinger.php | 4 +-- apps/user_webfinger/appinfo/install.php | 18 +++++++++++++- apps/user_webfinger/webfinger.php | 31 +++++++++++++----------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/apps/remoteStorage/appinfo/webfinger.php b/apps/remoteStorage/appinfo/webfinger.php index bb3fe1681b..7c0ab84605 100644 --- a/apps/remoteStorage/appinfo/webfinger.php +++ b/apps/remoteStorage/appinfo/webfinger.php @@ -1,6 +1,6 @@ + auth="/apps/remoteStorage/auth.php/"> diff --git a/apps/user_webfinger/appinfo/install.php b/apps/user_webfinger/appinfo/install.php index 678d57ae8f..c8d9a42742 100644 --- a/apps/user_webfinger/appinfo/install.php +++ b/apps/user_webfinger/appinfo/install.php @@ -1,4 +1,8 @@ '*', + 'Content-Type' => 'application/xml+xrd' +); $appInfoDir = __DIR__; $thisAppDir = dirname($appInfoDir); $appsDir = dirname($thisAppDir); @@ -17,6 +21,7 @@ if(isset($_SERVER['HTTPS'])) { } $lrddTmpl .= '://' . $serverName . $webRoot . '/apps/user_webfinger/webfinger.php?q={uri}'; $hostMetaPath = $docRoot . '/.well-known/host-meta'; +$hostMetaDir = $docRoot . '/.well-known'; $hostMetaContents = " " . $serverName . " @@ -24,7 +29,7 @@ $hostMetaContents = " Resource Descriptor "; -@mkdir(dirname($hostMetaPath)); +@mkdir($hostMetaDir); $hostMeta = fopen($hostMetaPath, 'w'); if(!$hostMeta) { die("Could not open " . $hostMetaPath . " for writing, please check permissions!"); @@ -33,3 +38,14 @@ if(!fwrite($hostMeta, $hostMetaContents, strlen($hostMetaContents))) { die("Could not write to " . $hostMetaPath . ", please check permissions!"); } fclose($hostMeta); + +// write custom headers into .htaccess: +$htaccess = fopen($hostMetaDir . '/.htaccess', 'w'); +//TODO: check compatibility! +fwrite($htaccess, " +\n"); +foreach($hostMetaHeader as $header => $value) { + fwrite($htaccess, "Header set " . $header . " \"" . $value . "\"\n"); +} +fwrite($htaccess, "\n"); +fclose($htaccess); diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php index ecbfeed8e4..9ada473ca8 100644 --- a/apps/user_webfinger/webfinger.php +++ b/apps/user_webfinger/webfinger.php @@ -6,13 +6,13 @@ header("Content-Type: application/xrd+xml"); * To include your app in the webfinger XML, add a new script with file name * 'webfinger.php' to /apps/yourapp/appinfo/, which prints out the XML parts * to be included. That script can make use of the constants WF_USER (e. g. - * "user"), WF_ADDRESS ("user@host") and WF_ROOT ("https://host/owncloud"). + * "user"), WF_ID (user@host) and WF_BASEURL (e. g. https://host/owncloud). * An example could look like this: * * + * href="/apps/myApp/profile.php?user="> * * '* but can also use complex database queries to generate the webfinger result @@ -24,19 +24,25 @@ $SERVERROOT=str_replace("\\",'/',dirname(dirname(dirname(dirname(__FILE__))))); $SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen($SERVERROOT)); $WEBROOT=substr($SUBURI,0,-34); */ -require_once('../../lib/base.php'); -$id = $_GET['q']; +require_once('../../lib/base.php'); +$request = urldecode($_GET['q']); if($_GET['q']) { - $bits = explode('@', $_GET['q']); - $userName = $bits[0]; + $reqParts = explode('@', $request); + $userName = $reqParts[0]; + $hostName = $reqParts[1]; } else { - $id = ''; $userName = ''; + $hostName = ''; } if(substr($userName, 0, 5) == 'acct:') { $userName = substr($userName, 5); } +if($userName == "") { + $id = ""; +} else { + $id = $userName . '@' . $hostName; +} if(isset($_SERVER['HTTPS'])) { $baseAddress = 'https://'; } else { @@ -44,22 +50,19 @@ if(isset($_SERVER['HTTPS'])) { } $baseAddress .= $_SERVER['SERVER_NAME'].OC::$WEBROOT; define('WF_USER', $userName); -define('WF_ADDRESS', $id); -define('WF_ROOT', $baseAddress); +define('WF_ID', $id); +define('WF_BASEURL', $baseAddress); echo "<"; ?> ?xml version="1.0" encoding="UTF-8"?> - - acct: + + acct: Date: Mon, 2 Apr 2012 17:12:52 +0200 Subject: [PATCH 14/37] webfinger protocol compatible + minor changes --- apps/remoteStorage/appinfo/webfinger.php | 4 +-- apps/user_webfinger/appinfo/install.php | 18 +++++++++++++- apps/user_webfinger/webfinger.php | 31 +++++++++++++----------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/apps/remoteStorage/appinfo/webfinger.php b/apps/remoteStorage/appinfo/webfinger.php index bb3fe1681b..7c0ab84605 100644 --- a/apps/remoteStorage/appinfo/webfinger.php +++ b/apps/remoteStorage/appinfo/webfinger.php @@ -1,6 +1,6 @@ + auth="/apps/remoteStorage/auth.php/"> diff --git a/apps/user_webfinger/appinfo/install.php b/apps/user_webfinger/appinfo/install.php index 678d57ae8f..c8d9a42742 100644 --- a/apps/user_webfinger/appinfo/install.php +++ b/apps/user_webfinger/appinfo/install.php @@ -1,4 +1,8 @@ '*', + 'Content-Type' => 'application/xml+xrd' +); $appInfoDir = __DIR__; $thisAppDir = dirname($appInfoDir); $appsDir = dirname($thisAppDir); @@ -17,6 +21,7 @@ if(isset($_SERVER['HTTPS'])) { } $lrddTmpl .= '://' . $serverName . $webRoot . '/apps/user_webfinger/webfinger.php?q={uri}'; $hostMetaPath = $docRoot . '/.well-known/host-meta'; +$hostMetaDir = $docRoot . '/.well-known'; $hostMetaContents = " " . $serverName . " @@ -24,7 +29,7 @@ $hostMetaContents = " Resource Descriptor "; -@mkdir(dirname($hostMetaPath)); +@mkdir($hostMetaDir); $hostMeta = fopen($hostMetaPath, 'w'); if(!$hostMeta) { die("Could not open " . $hostMetaPath . " for writing, please check permissions!"); @@ -33,3 +38,14 @@ if(!fwrite($hostMeta, $hostMetaContents, strlen($hostMetaContents))) { die("Could not write to " . $hostMetaPath . ", please check permissions!"); } fclose($hostMeta); + +// write custom headers into .htaccess: +$htaccess = fopen($hostMetaDir . '/.htaccess', 'w'); +//TODO: check compatibility! +fwrite($htaccess, " +\n"); +foreach($hostMetaHeader as $header => $value) { + fwrite($htaccess, "Header set " . $header . " \"" . $value . "\"\n"); +} +fwrite($htaccess, "\n"); +fclose($htaccess); diff --git a/apps/user_webfinger/webfinger.php b/apps/user_webfinger/webfinger.php index ecbfeed8e4..9ada473ca8 100644 --- a/apps/user_webfinger/webfinger.php +++ b/apps/user_webfinger/webfinger.php @@ -6,13 +6,13 @@ header("Content-Type: application/xrd+xml"); * To include your app in the webfinger XML, add a new script with file name * 'webfinger.php' to /apps/yourapp/appinfo/, which prints out the XML parts * to be included. That script can make use of the constants WF_USER (e. g. - * "user"), WF_ADDRESS ("user@host") and WF_ROOT ("https://host/owncloud"). + * "user"), WF_ID (user@host) and WF_BASEURL (e. g. https://host/owncloud). * An example could look like this: * * + * href="/apps/myApp/profile.php?user="> * * '* but can also use complex database queries to generate the webfinger result @@ -24,19 +24,25 @@ $SERVERROOT=str_replace("\\",'/',dirname(dirname(dirname(dirname(__FILE__))))); $SUBURI=substr(realpath($_SERVER["SCRIPT_FILENAME"]),strlen($SERVERROOT)); $WEBROOT=substr($SUBURI,0,-34); */ -require_once('../../lib/base.php'); -$id = $_GET['q']; +require_once('../../lib/base.php'); +$request = urldecode($_GET['q']); if($_GET['q']) { - $bits = explode('@', $_GET['q']); - $userName = $bits[0]; + $reqParts = explode('@', $request); + $userName = $reqParts[0]; + $hostName = $reqParts[1]; } else { - $id = ''; $userName = ''; + $hostName = ''; } if(substr($userName, 0, 5) == 'acct:') { $userName = substr($userName, 5); } +if($userName == "") { + $id = ""; +} else { + $id = $userName . '@' . $hostName; +} if(isset($_SERVER['HTTPS'])) { $baseAddress = 'https://'; } else { @@ -44,22 +50,19 @@ if(isset($_SERVER['HTTPS'])) { } $baseAddress .= $_SERVER['SERVER_NAME'].OC::$WEBROOT; define('WF_USER', $userName); -define('WF_ADDRESS', $id); -define('WF_ROOT', $baseAddress); +define('WF_ID', $id); +define('WF_BASEURL', $baseAddress); echo "<"; ?> ?xml version="1.0" encoding="UTF-8"?> - - acct: + + acct: Date: Mon, 2 Apr 2012 16:35:11 +0000 Subject: [PATCH 15/37] use OC_Dialogs instead of alert() --- apps/files_texteditor/js/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 02d39b9843..9a87601a4f 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -210,7 +210,7 @@ function showFileEditor(dir,filename){ }); } else { // Failed to get the file. - alert(result.data.message); + OC.dialogs.alert(result.data.message, t('files_texteditor','An error occurred!')); } // End success } From dc499c5b4e9dc1c64ca81487bfa979121bd407f6 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Mon, 2 Apr 2012 17:27:06 +0000 Subject: [PATCH 16/37] add * to filename when changes have been made --- apps/files_texteditor/js/editor.js | 68 ++++++++++++++++++------------ 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 9a87601a4f..ca6a3a965f 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -141,31 +141,38 @@ function doSearch(){ // Tries to save the file. function doFileSave(){ if(editorIsShown()){ - // Get file path - var path = $('#editor').attr('data-dir')+'/'+$('#editor').attr('data-filename'); - // Get original mtime - var mtime = $('#editor').attr('data-mtime'); - // Show saving spinner - $("#editor_save").die('click',doFileSave); - $('#save_result').remove(); - $('#editor_save').text(t('files_texteditor','Saving...')); - // Get the data - var filecontents = window.aceEditor.getSession().getValue(); - // Send the data - $.post(OC.filePath('files_texteditor','ajax','savefile.php'), { filecontents: filecontents, path: path, mtime: mtime },function(jsondata){ - if(jsondata.status!='success'){ - // Save failed - $('#editor_save').text(t('files_texteditor','Save')); - $('#editor_save').after('

Failed to save file

'); - $("#editor_save").live('click',doFileSave); - } else { - // Save OK - // Update mtime - $('#editor').attr('data-mtime',jsondata.data.mtime); - $('#editor_save').text(t('files_texteditor','Save')); - $("#editor_save").live('click',doFileSave); - } - },'json'); + // Changed contents? + if($('#editor').attr('data-edited')=='true'){ + // Get file path + var path = $('#editor').attr('data-dir')+'/'+$('#editor').attr('data-filename'); + // Get original mtime + var mtime = $('#editor').attr('data-mtime'); + // Show saving spinner + $("#editor_save").die('click',doFileSave); + $('#save_result').remove(); + $('#editor_save').text(t('files_texteditor','Saving...')); + // Get the data + var filecontents = window.aceEditor.getSession().getValue(); + // Send the data + $.post(OC.filePath('files_texteditor','ajax','savefile.php'), { filecontents: filecontents, path: path, mtime: mtime },function(jsondata){ + if(jsondata.status!='success'){ + // Save failed + $('#editor_save').text(t('files_texteditor','Save')); + $('#editor_save').after('

Failed to save file

'); + $("#editor_save").live('click',doFileSave); + } else { + // Save OK + // Update mtime + $('#editor').attr('data-mtime',jsondata.data.mtime); + $('#editor_save').text(t('files_texteditor','Save')); + $("#editor_save").live('click',doFileSave); + // Update titles + $('#editor').attr('data-edited', 'false'); + $('#breadcrumb_file').text($('#editor').attr('data-filename')); + document.title = $('#editor').attr('data-filename')+' - ownCloud'; + } + },'json'); + } } }; @@ -192,10 +199,11 @@ function showFileEditor(dir,filename){ // Show the control bar showControls(filename,result.data.write); // Update document title - document.title = filename; + document.title = filename+' - ownCloud'; $('#editor').text(result.data.filecontents); $('#editor').attr('data-dir', dir); $('#editor').attr('data-filename', filename); + $('#editor').attr('data-edited', 'false'); window.aceEditor = ace.edit("editor"); aceEditor.setShowPrintMargin(false); aceEditor.getSession().setUseWrapMode(true); @@ -207,6 +215,13 @@ function showFileEditor(dir,filename){ OC.addScript('files_texteditor','aceeditor/theme-clouds', function(){ window.aceEditor.setTheme("ace/theme/clouds"); }); + window.aceEditor.getSession().on('change', function(){ + if($('#editor').attr('data-edited')!='true'){ + $('#editor').attr('data-edited', 'true'); + $('#breadcrumb_file').text($('#breadcrumb_file').text()+' *'); + document.title = $('#editor').attr('data-filename')+' * - ownCloud'; + } + }); }); } else { // Failed to get the file. @@ -287,4 +302,5 @@ $(document).ready(function(){ $('#editor').remove(); // Binds the save keyboard shortcut events //$(document).unbind('keydown').bind('keydown',checkForSaveKeyPress); + }); From f21d6d4f9fcd48ffe4e2e42b4f3a4e8b7bcfd142 Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Mon, 2 Apr 2012 19:39:24 +0200 Subject: [PATCH 17/37] dialogs filepicker first draft --- core/css/styles.css | 6 +++ core/js/js.js | 8 +++- core/js/oc-dialogs.js | 91 ++++++++++++++++++++++++++++++++++++------ files/ajax/rawlist.php | 23 +++++++++++ 4 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 files/ajax/rawlist.php diff --git a/core/css/styles.css b/core/css/styles.css index f5a181c452..1c50df9e58 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -131,3 +131,9 @@ li.error { width:640px; margin:4em auto; padding:1em 1em 1em 4em; background:#ff .separator { display: inline; border-left: 1px solid #d3d3d3; border-right: 1px solid #fff; height: 10px; width:0px; margin: 4px; } a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padding-top: 0px;padding-bottom: 2px; text-decoration: none; margin-top: 5px } + +/* ---- DIALOGS ---- */ + +#dirtree {width: 100%;} +#filelist {height: 270px; overflow:scroll; background-color: white;} +.filepicker_element_selected { background-color: lightblue;} diff --git a/core/js/js.js b/core/js/js.js index df1b5c6ce7..44b4f503b8 100644 --- a/core/js/js.js +++ b/core/js/js.js @@ -126,7 +126,13 @@ OC={ }); } }, - dialogs:OCdialogs + dialogs:OCdialogs, + mtime2date:function(mtime) { + mtime = parseInt(mtime); + var date = new Date(1000*mtime); + var ret = date.getDate()+'.'+(date.getMonth()+1)+'.'+date.getFullYear()+', '+date.getHours()+':'+date.getMinutes(); + return ret; + } }; OC.search.customResults={}; OC.search.currentResult=-1; diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 17c987ae87..31aa76d96c 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -17,7 +17,6 @@ * You should have received a copy of the GNU Affero General Public * License along with this library. If not, see . * - * todo(bartek): add select option in form */ /** @@ -30,9 +29,9 @@ OCdialogs = { * @param title dialog title * @param callback which will be triggered when user press OK */ - alert:function(text, title, callback) { + alert:function(text, title, callback, modal) { var content = '

'+text+'

'; - OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback); + OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback, modal); }, /** * displays info dialog @@ -40,9 +39,9 @@ OCdialogs = { * @param title dialog title * @param callback which will be triggered when user press OK */ - info:function(text, title, callback) { + info:function(text, title, callback, modal) { var content = '

'+text+'

'; - OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback); + OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.OK_BUTTON, callback, modal); }, /** * displays confirmation dialog @@ -50,9 +49,9 @@ OCdialogs = { * @param title dialog title * @param callback which will be triggered when user press YES or NO (true or false would be passed to callback respectively) */ - confirm:function(text, title, callback) { + confirm:function(text, title, callback, modal) { var content = '

'+text+'

'; - OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.YES_NO_BUTTONS, callback); + OCdialogs.message(content, title, OCdialogs.ALERT_DIALOG, OCdialogs.YES_NO_BUTTONS, callback, modal); }, /** * prompt for user input @@ -60,9 +59,9 @@ OCdialogs = { * @param title dialog title * @param callback which will be triggered when user press OK (input text will be passed to callback) */ - prompt:function(text, title, default_value, callback) { + prompt:function(text, title, default_value, callback, modal) { var content = '

'+text+':

'; - OCdialogs.message(content, title, OCdialogs.PROMPT_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback); + OCdialogs.message(content, title, OCdialogs.PROMPT_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback, modal); }, /** * prompt user for input with custom form @@ -71,7 +70,7 @@ OCdialogs = { * @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) { + form:function(fields, title, callback, modal) { var content = ''; for (var a in fields) { content += ''; } content += '
'+fields[a].text+''; @@ -96,12 +95,41 @@ OCdialogs = { content += '
'; - OCdialogs.message(content, title, OCdialogs.FORM_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback); + OCdialogs.message(content, title, OCdialogs.FORM_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback, modal); }, - message:function(content, title, dialog_type, buttons, callback) { + filepicker:function(title, name_filter, mimetype_filter, callback, modal) { + var c_name = 'oc-dialog-'+OCdialogs.dialogs_counter+'-content'; + var c_id = '#'+c_name; + var d = '
'; + if (modal == undefined) modal = false; + $('body').append(d); + $(c_id + ' #dirtree').focus(function() { var t = $(this); t.data('oldval', t.val())}) + .change({dcid: c_id}, OC.dialogs.handleTreeListSelect); + $(c_id).ready(function(){ + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', function(r){OC.dialogs.fillFilePicker(r, c_id, callback)}); + }); + // build buttons + var b = [ + {text: t('dialogs', 'Choose'), click: function(){ + if (callback != undefined) { + var p = $(c_id).attr('data'); + if (p == undefined) p = ''; + callback(p+'/'+$(c_id+' .filepicker_element_selected #filename').text()); + $(c_id).dialog('close'); + } + } + }, + {text: t('dialogs', 'Cancel'), click: function(){$(c_id).dialog('close'); }} + ]; + $(c_id).dialog({width: 4*$(document).width()/9, height: 400, modal: modal, buttons: b}); + OCdialogs.dialogs_counter++; + }, + // guts, dont use, dont touch + message:function(content, title, dialog_type, buttons, callback, modal) { var c_name = 'oc-dialog-'+OCdialogs.dialogs_counter+'-content'; var c_id = '#'+c_name; var d = '
'+content+'
'; + if (modal == undefined) modal = false; $('body').append(d); var b = []; switch (buttons) { @@ -128,7 +156,7 @@ OCdialogs = { break; } var possible_height = ($('tr', d).size()+1)*30; - $(c_id).dialog({width: 4*$(document).width()/9, height: possible_height + 120, modal: false, buttons: b}); + $(c_id).dialog({width: 4*$(document).width()/9, height: possible_height + 120, modal: modal, buttons: b}); OCdialogs.dialogs_counter++; }, // dialogs buttons types @@ -161,5 +189,42 @@ OCdialogs = { } else { $(c_id).dialog('close'); } + }, + fillFilePicker:function(r, dialog_content_id) { + var entry_template = '
*NAME*
*LASTMODDATE*
'; + 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*', OC.webroot+'/core/img/filetypes/'+(r.data[a].type=='dir'?'folder':r.data[a].mimetype.replace('/','-'))+'.png').replace('*ENTRYNAME*', r.data[a].name).replace('*ENTRYTYPE*', r.data[a].type); + } + $(dialog_content_id + ' #filelist').html(names); + }, + handleTreeListSelect:function(event) { + var newval = parseInt($(this).val()); + var oldval = parseInt($(this).data('oldval')); + while (newval != oldval && oldval > 0) { + $('option:last', this).remove(); + $('option:last', this).attr('selected','selected'); + oldval--; + } + var skip_first = true; + var path = ''; + $(this).children().each(function(i, element) { if (skip_first) {skip_first = false; return; }path += '/'+$(element).text(); }); + $(event.data.dcid).attr('data', path); + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)}); + }, + // this function is in early development state, please dont use it unlsess you know what you are doing + handlePickerClick:function(element, name, dcid) { + var p = $(dcid).attr('data'); + if (p == undefined) p = ''; + p = p+'/'+name; + if ($(element).attr('data') == 'file'){ + $(element).toggleClass('filepicker_element_selected'); + return; + } + $(dcid).attr('data', p); + $(dcid + ' #dirtree option:last').removeAttr('selected'); + var newval = parseInt($(dcid + ' #dirtree option:last').val())+1; + $(dcid + ' #dirtree').append(''); + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: p}, function(r){OC.dialogs.fillFilePicker(r, dcid)}); } }; diff --git a/files/ajax/rawlist.php b/files/ajax/rawlist.php new file mode 100644 index 0000000000..0abe81e672 --- /dev/null +++ b/files/ajax/rawlist.php @@ -0,0 +1,23 @@ + $files)); + +?> From adc9d906e4b45082dc08463afce6835a49feb438 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Mon, 2 Apr 2012 17:44:15 +0000 Subject: [PATCH 18/37] confirm close when there are unsaved changes --- apps/files_texteditor/js/editor.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index ca6a3a965f..1e136fe68e 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -76,7 +76,7 @@ function showControls(filename,writeperms){ function bindControlEvents(){ $("#editor_save").die('click',doFileSave).live('click',doFileSave); - $('#editor_close').die('click',hideFileEditor).live('click',hideFileEditor); + $('#editor_close').die('click',closeBtnClick).live('click',closeBtnClick); $('#gotolineval').die('keyup', goToLine).live('keyup', goToLine); $('#editorsearchval').die('keyup', doSearch).live('keyup', doSearch); $('#clearsearchbtn').die('click', resetSearch).live('click', resetSearch); @@ -235,6 +235,19 @@ function showFileEditor(dir,filename){ } } +function closeBtnClick(){ + if($('#editor').attr('data-edited')=='true'){ + // Show confirm + OC.dialogs.confirm(t('files_texteditor','You have unsaved changes that will be lost! Do you still want to close?'),t('files_texteditor','Really close?'),function(close){ + if(close){ + hideFileEditor(); + } + }); + } else { + hideFileEditor(); + } +} + // Fades out the editor. function hideFileEditor(){ // Fades out editor controls From ff5dbc52b8137bc1d4e082c422049271d5f89978 Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Mon, 2 Apr 2012 21:31:34 +0200 Subject: [PATCH 19/37] multiselect handle for filepicker --- core/js/oc-dialogs.js | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 31aa76d96c..d40c433bda 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -97,24 +97,34 @@ OCdialogs = { content += ''; OCdialogs.message(content, title, OCdialogs.FORM_DIALOG, OCdialogs.OK_CANCEL_BUTTONS, callback, modal); }, - filepicker:function(title, name_filter, mimetype_filter, 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 = '
'; - if (modal == undefined) modal = false; + if (!modal) modal = false; + if (!multiselect) multiselect = false; $('body').append(d); $(c_id + ' #dirtree').focus(function() { var t = $(this); t.data('oldval', t.val())}) .change({dcid: c_id}, OC.dialogs.handleTreeListSelect); $(c_id).ready(function(){ $.getJSON(OC.webroot+'/files/ajax/rawlist.php', function(r){OC.dialogs.fillFilePicker(r, c_id, callback)}); - }); + }).data('multiselect', multiselect); // build buttons var b = [ {text: t('dialogs', 'Choose'), click: function(){ if (callback != undefined) { - var p = $(c_id).attr('data'); - if (p == undefined) p = ''; - callback(p+'/'+$(c_id+' .filepicker_element_selected #filename').text()); + var p; + if ($(c_id).data('multiselect') == true) { + p = []; + $(c_id+' .filepicker_element_selected #filename').each(function(i, elem) { + p.push(($(c_id).data('path')?$(c_id).data('path'):'')+'/'+$(elem).text()); + }); + } else { + var p = $(c_id).data('path'); + if (p == undefined) p = ''; + p = p+'/'+$(c_id+' .filepicker_element_selected #filename').text() + } + callback(p); $(c_id).dialog('close'); } } @@ -209,19 +219,21 @@ OCdialogs = { var skip_first = true; var path = ''; $(this).children().each(function(i, element) { if (skip_first) {skip_first = false; return; }path += '/'+$(element).text(); }); - $(event.data.dcid).attr('data', path); + $(event.data.dcid).data('path', path); $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)}); }, // this function is in early development state, please dont use it unlsess you know what you are doing handlePickerClick:function(element, name, dcid) { - var p = $(dcid).attr('data'); + var p = $(dcid).data('path'); if (p == undefined) p = ''; p = p+'/'+name; if ($(element).attr('data') == 'file'){ + if ($(dcid).data('multiselect') != true) + $(dcid+' .filepicker_element_selected').removeClass('filepicker_element_selected'); $(element).toggleClass('filepicker_element_selected'); return; } - $(dcid).attr('data', p); + $(dcid).data('path', p); $(dcid + ' #dirtree option:last').removeAttr('selected'); var newval = parseInt($(dcid + ' #dirtree option:last').val())+1; $(dcid + ' #dirtree').append(''); From 896bff57480448456b2ca7d57f5ff2b0439315f6 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Thu, 29 Mar 2012 18:54:06 +0200 Subject: [PATCH 20/37] Contacts: rescan categories on load if there are none. --- apps/contacts/index.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/apps/contacts/index.php b/apps/contacts/index.php index 04f6c65a14..076b10c2ee 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -34,7 +34,28 @@ if(!is_null($id)) { } $property_types = OC_Contacts_App::getAddPropertyOptions(); $phone_types = OC_Contacts_App::getTypesOfProperty('TEL'); -$categories = OC_Contacts_App::$categories->categories(); +$categories = OC_Contacts_App::getCategories(); +if(count($categories) == 0) { + $vcaddressbooks = OC_Contacts_Addressbook::all(OC_User::getUser()); + if(count($vcaddressbooks) > 0) { + $vcaddressbookids = array(); + foreach($vcaddressbooks as $vcaddressbook) { + $vcaddressbookids[] = $vcaddressbook['id']; + } + $vccontacts = OC_Contacts_VCard::all($vcaddressbookids); + if(count($vccontacts) == 0) { + bailOut(OC_Contacts_App::$l10n->t('No contacts found.')); + } + + $cards = array(); + foreach($vccontacts as $vccontact) { + $cards[] = $vccontact['carddata']; + } + + OC_Contacts_App::$categories->rescan($cards); + $categories = OC_Contacts_App::$categories->categories(); + } +} $upload_max_filesize = OC_Helper::computerFileSize(ini_get('upload_max_filesize')); $post_max_size = OC_Helper::computerFileSize(ini_get('post_max_size')); @@ -61,7 +82,6 @@ $tmpl = new OC_Template( "contacts", "index", "user" ); $tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); $tmpl->assign('uploadMaxHumanFilesize', OC_Helper::humanFileSize($maxUploadFilesize)); $tmpl->assign('property_types',$property_types); -$tmpl->assign('categories',OC_Contacts_App::getCategories()); $tmpl->assign('phone_types',$phone_types); $tmpl->assign('categories',$categories); $tmpl->assign('addressbooks', $addressbooks); From b3f107dddaf4f3b5b65d8dd67d66bf1bd36d9ae1 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 3 Apr 2012 03:28:12 +0200 Subject: [PATCH 21/37] Contacts: First work on cleaner design. --- apps/contacts/ajax/addcontact.php | 5 +- apps/contacts/css/contacts.css | 32 ++++---- apps/contacts/img/person_large.png | Bin 11517 -> 7929 bytes apps/contacts/js/contacts.js | 74 ++++++++++-------- apps/contacts/js/jquery.combobox.js | 23 +++--- apps/contacts/js/jquery.multi-autocomplete.js | 4 +- apps/contacts/templates/part.contact.php | 73 ++++++++--------- 7 files changed, 113 insertions(+), 98 deletions(-) diff --git a/apps/contacts/ajax/addcontact.php b/apps/contacts/ajax/addcontact.php index 839a391998..947b35bab5 100644 --- a/apps/contacts/ajax/addcontact.php +++ b/apps/contacts/ajax/addcontact.php @@ -39,7 +39,10 @@ foreach ($_POST as $key=>$element) { debug('_POST: '.$key.'=>'.$element); } -$aid = $_POST['aid']; +$aid = isset($_POST['aid'])?$_POST['aid']:null; +if(!$aid) { + $aid = min(OC_Contacts_Addressbook::activeIds()); // first active addressbook. +} OC_Contacts_App::getAddressbook( $aid ); // is owner access check $fn = trim($_POST['fn']); diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 76b5972ba3..9d238c36f3 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -14,21 +14,21 @@ #contacts_propertymenu li:hover { background-color: #1d2d44; } #contacts_propertymenu li a:hover { color: #fff } #actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0;} -#card { /*max-width: 70em; border: thin solid lightgray; display: block;*/ } +#card { width: auto;/*max-width: 70em; border: thin solid lightgray; display: block;*/ } #firstrun { width: 100%; position: absolute; top: 5em; left: 0; text-align: center; font-weight:bold; font-size:1.5em; color:#777; } #firstrun #selections { font-size:0.8em; margin: 2em auto auto auto; clear: both; } -#card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; } +#card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; float: left; } .categories { float: left; width: 16em; } -#card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select { background-color: #f8f8f8; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; } +#card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select { background-color: #fefefe; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; } #card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } -input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid { background-color: #ffc0c0 !important; } +input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid { color: #bbb !important; } dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } -.form dt { display: table-cell; clear: left; float: left; width: 7em; margin: 0; padding: 0.8em 0.5em 0 0; font-weight: bold; text-align:right; text-overflow:ellipsis; o-text-overflow: ellipsis; vertical-align: text-bottom;/* white-space: pre-wrap; white-space: -moz-pre-wrap !important; white-space: -pre-wrap; white-space: -o-pre-wrap;*/ } +.form dt { display: table-cell; clear: left; float: left; width: 7em; margin: 0; padding: 0.8em 0.5em 0 0; text-align:right; text-overflow:ellipsis; o-text-overflow: ellipsis; vertical-align: text-bottom; color: #bbb;/* white-space: pre-wrap; white-space: -moz-pre-wrap !important; white-space: -pre-wrap; white-space: -o-pre-wrap;*/ } .form dd { display: table-cell; clear: right; float: left; margin: 0; padding: 0px; white-space: nowrap; vertical-align: text-bottom; } .loading { background: url('../../../core/img/loading.gif') no-repeat center !important; /*cursor: progress; */ cursor: wait; } - +.float { float: left; } .listactions { height: 1em; width:60px; float: left; clear: right; } .add,.edit,.delete,.mail, .globe { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; display: none; } .add { background:url('../../../core/img/actions/add.svg') no-repeat center; clear: both; } @@ -43,18 +43,18 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } #edit_address_dialog { /*width: 30em;*/ } #edit_address_dialog > input { width: 15em; } #edit_photo_dialog_img { display: block; width: 150; height: 200; border: thin solid black; } -#fn { float: left; } -/** - * Create classes form, floateven and floatodd which flows left and right respectively. - */ -.contactsection { float: left; min-width: 30em; max-width: 40em; margin: 0.5em; border: thin solid lightgray; -webkit-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; background-color: #f8f8f8; } +#fn { float: left !important; width: 18em !important; } +#name { /*position: absolute; top: 0px; left: 0px;*/ min-width: 25em; height: 2em; clear: right; display: block; } +#identityprops { /*position: absolute; top: 2.5em; left: 0px;*/ } +/*#contact_photo { max-width: 250px; }*/ +#contact_identity { min-width: 30em; } +.contactsection { position: relative; float: left; /*max-width: 40em;*/ padding: 0.5em; height: auto: border: thin solid lightgray;/* -webkit-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; background-color: #f8f8f8;*/ } .contactpart legend { width:auto; padding:.3em; border:1px solid #ddd; font-weight:bold; cursor:pointer; background:#f8f8f8; color:#555; text-shadow:#fff 0 1px 0; -moz-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 1px #fff inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; } #cropbox { margin: auto; } - -#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; padding: 0.5em; margin: 1em 1em 1em 7em; cursor: pointer; background: url(../../../core/img/loading.gif) no-repeat center center; clear: right; } +#contacts_details_photo { border-radius: 0.5em; border: thin solid #bbb; padding: 0.5em; margin: 0.3em; cursor: pointer; background: url(../../../core/img/loading.gif) no-repeat center center; display: block; /* clear: right;*/ } #contacts_details_photo:hover { background: #fff; } -#contacts_details_photo_progress { margin: 0.3em 0.3em 0.3em 7em; clear: left; } +/*#contacts_details_photo_progress { margin: 0.3em 0.3em 0.3em 7em; clear: left; }*/ /* Address editor */ #addressdisplay { padding: 0.5em; } dl.addresscard { background-color: #fff; float: left; width: 45%; margin: 0 0.3em 0.3em 0.3em; padding: 0; border: thin solid lightgray; } @@ -72,8 +72,10 @@ dl.addresscard dd > ul { margin: 0.3em; padding: 0.3em; } #file_upload_target, #crop_target { display:none; } -#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; position:absolute; left:0; top:0; cursor:pointer; width:0; height:0;} +#file_upload_start { opacity:0; filter:alpha(opacity=0); z-index:1; /*position:absolute; left:0; top:0;*/ cursor:pointer; width:0; height:0;} input[type="checkbox"] { width: 20px; height: 20px; vertical-align: bottom; } +.big { font-weight:bold; font-size:1.2em; } +.huge { font-weight:bold; font-size:1.5em; } .propertycontainer dd { float: left; width: 25em; } .propertylist { clear: none; max-width: 28em; } .propertylist li { /*background-color: cyan; */ min-width: 25em; /*max-width: 30em;*/ display: block; clear: right; } diff --git a/apps/contacts/img/person_large.png b/apps/contacts/img/person_large.png index f57511e1000690c223bc5de2313ddfface12f29a..4edba0c5489d1e92b35f9f813189bd8b7c391f17 100644 GIT binary patch literal 7929 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 G-Twfpl}P*m diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index d314878cc0..e838d713d4 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -65,7 +65,7 @@ Contacts={ propertyTypeFor:function(obj) { return $(obj).parents('.propertycontainer').first().data('element'); }, - showHideContactInfo:function() { + /*showHideContactInfo:function() { var show = ($('#emaillist li.propertycontainer').length > 0 || $('#phonelist li.propertycontainer').length > 0 || $('#addressdisplay dl.propertycontainer').length > 0); console.log('showHideContactInfo: ' + show); if(show) { @@ -73,8 +73,8 @@ Contacts={ } else { $('#contact_communication').hide(); } - }, - checkListFor:function(obj) { + },*/ + /*checkListFor:function(obj) { var type = $(obj).parents('.propertycontainer').first().data('element'); console.log('checkListFor: ' + type); switch (type) { @@ -101,7 +101,7 @@ Contacts={ case 'BDAY': break; } - }, + },*/ loading:function(obj, state) { if(state) { $(obj).addClass('loading'); @@ -137,18 +137,14 @@ Contacts={ $(this).find('.add').fadeOut(500); } );*/ - $('.button,.action').tipsy(); - $('#contacts_deletecard').tipsy({gravity: 'ne'}); - $('#contacts_downloadcard').tipsy({gravity: 'ne'}); //$('#fn').jec(); $('#fn_select').combobox({ 'id': 'fn', 'name': 'value', - 'classes': ['contacts_property'], + 'classes': ['contacts_property', 'huge', 'tip', 'float'], + 'attributes': {'placeholder': t('contacts', 'Enter name')}, 'title': t('contacts', 'Format custom, Short name, Full name, Reverse or Reverse with comma')}); //$('.jecEditableOption').attr('title', t('contacts','Custom')); - $('#fn').tipsy(); - $('#contacts_details_photo_wrapper').tipsy(); $('#bday').datepicker({ dateFormat : 'dd-mm-yy' }); @@ -200,6 +196,9 @@ Contacts={ } ] ); $('#categories').multiple_autocomplete({source: categories}); + $('.button,.action,.tip').tipsy(); + $('#contacts_deletecard').tipsy({gravity: 'ne'}); + $('#contacts_downloadcard').tipsy({gravity: 'ne'}); Contacts.UI.loadListHandlers(); }, Card:{ @@ -267,7 +266,7 @@ Contacts={ import:function(){ Contacts.UI.notImplemented(); }, - add:function(n, fn, aid){ // add a new contact + add:function(n, fn, aid, isnew){ // add a new contact console.log('Add contact: ' + n + ', ' + fn + ' ' + aid); $.post(OC.filePath('contacts', 'ajax', 'addcontact.php'), { n: n, fn: fn, aid: aid }, function(jsondata) { @@ -291,7 +290,15 @@ Contacts={ if(!added) { $('#leftcontent ul').append(item); } - + if(isnew) { + Contacts.UI.Card.addProperty('EMAIL'); + Contacts.UI.Card.addProperty('TEL'); + Contacts.UI.Card.addProperty('BDAY'); + Contacts.UI.Card.addProperty('NICKNAME'); + Contacts.UI.Card.addProperty('ORG'); + Contacts.UI.Card.addProperty('CATEGORIES'); + $('#fn').focus(); + } } else{ OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); @@ -356,7 +363,7 @@ Contacts={ return false; }, loadContact:function(jsondata){ - $('#contact_communication').hide(); + //$('#contact_communication').hide(); this.data = jsondata; this.id = this.data.id; $('#rightcontent').data('id',this.id); @@ -368,7 +375,6 @@ Contacts={ this.loadPhones(); this.loadAddresses(); this.loadSingleProperties(); - // TODO: load NOTE ;-) if(this.data.NOTE) { $('#note').data('checksum', this.data.NOTE[0]['checksum']); $('#note').find('textarea').val(this.data.NOTE[0]['value']); @@ -376,7 +382,7 @@ Contacts={ } else { $('#note').data('checksum', ''); $('#note').find('textarea').val(''); - $('#note').hide(); + //$('#note').hide(); } }, loadSingleProperties:function() { @@ -521,17 +527,18 @@ Contacts={ },*/ editNew:function(){ // add a new contact this.id = ''; this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''; - $.getJSON(OC.filePath('contacts', 'ajax', 'newcontact.php'),{},function(jsondata){ + Contacts.UI.Card.add(';;;;', '', '', true); + /*$.getJSON(OC.filePath('contacts', 'ajax', 'newcontact.php'),{},function(jsondata){ if(jsondata.status == 'success'){ id = ''; $('#rightcontent').data('id',''); $('#rightcontent').html(jsondata.data.page); - Contacts.UI.Card.editName(); + //Contacts.UI.Card.editName(); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); //alert(jsondata.data.message); } - }); + });*/ }, savePropertyInternal:function(name, fields, oldchecksum, checksum){ // TODO: Add functionality for new fields. @@ -627,8 +634,8 @@ Contacts={ },'json'); } }, - addProperty:function(obj){ - var type = $(obj).data('type'); + addProperty:function(type){ + //var type = $(obj).data('type'); console.log('addProperty:' + type); switch (type) { case 'PHOTO': @@ -647,21 +654,21 @@ Contacts={ $('#emails').show(); } Contacts.UI.Card.addMail(); - Contacts.UI.showHideContactInfo(); + //Contacts.UI.showHideContactInfo(); break; case 'TEL': if($('#phonelist>li').length == 1) { $('#phones').show(); } Contacts.UI.Card.addPhone(); - Contacts.UI.showHideContactInfo(); + //Contacts.UI.showHideContactInfo(); break; case 'ADR': if($('#addressdisplay>dl').length == 1) { $('#addresses').show(); } Contacts.UI.Card.editAddress('new', true); - Contacts.UI.showHideContactInfo(); + //Contacts.UI.showHideContactInfo(); break; case 'NICKNAME': case 'ORG': @@ -682,8 +689,8 @@ Contacts={ if(jsondata.status == 'success'){ if(type == 'list') { Contacts.UI.propertyContainerFor(obj).remove(); - Contacts.UI.showHideContactInfo(); - Contacts.UI.checkListFor(obj); + //Contacts.UI.showHideContactInfo(); + //Contacts.UI.checkListFor(obj); } else if(type == 'single') { var proptype = Contacts.UI.propertyTypeFor(obj); console.log('deleteProperty, hiding: ' + proptype); @@ -718,8 +725,8 @@ Contacts={ } else { // Property hasn't been saved so there's nothing to delete. if(type == 'list') { Contacts.UI.propertyContainerFor(obj).remove(); - Contacts.UI.showHideContactInfo(); - Contacts.UI.checkListFor(obj); + //Contacts.UI.showHideContactInfo(); + //Contacts.UI.checkListFor(obj); } else if(type == 'single') { var proptype = Contacts.UI.propertyTypeFor(obj); console.log('deleteProperty, hiding: ' + proptype); @@ -891,7 +898,7 @@ Contacts={ if(isnew) { container.remove(); } - Contacts.UI.showHideContactInfo(); + //Contacts.UI.showHideContactInfo(); } }, close : function(event, ui) { @@ -900,7 +907,7 @@ Contacts={ if(isnew) { container.remove(); } - Contacts.UI.showHideContactInfo(); + //Contacts.UI.showHideContactInfo(); }/*, open : function(event, ui) { // load 'ADR' property - maybe :-P @@ -973,7 +980,7 @@ Contacts={ } }, loadPhoto:function(force){ - if(this.data.PHOTO||force==true) { + //if(this.data.PHOTO||force==true) { $.getJSON('ajax/loadphoto.php',{'id':this.id},function(jsondata){ if(jsondata.status == 'success'){ //alert(jsondata.data.page); @@ -986,11 +993,11 @@ Contacts={ }); $('#file_upload_form').show(); $('#contacts_propertymenu a[data-type="PHOTO"]').parent().hide(); - } else { + /*} else { $('#contacts_details_photo_wrapper').empty(); $('#file_upload_form').hide(); $('#contacts_propertymenu a[data-type="PHOTO"]').parent().show(); - } + }*/ }, editPhoto:function(id, tmp_path){ //alert('editPhoto: ' + tmp_path); @@ -1430,7 +1437,8 @@ $(document).ready(function(){ } }); $('#contacts_propertymenu a').live('click',function(){ - Contacts.UI.Card.addProperty(this); + var type = $(this).data('type'); + Contacts.UI.Card.addProperty(type); $('#contacts_propertymenu').hide(); }); }); diff --git a/apps/contacts/js/jquery.combobox.js b/apps/contacts/js/jquery.combobox.js index 6da4ecb514..f46d7c14c1 100644 --- a/apps/contacts/js/jquery.combobox.js +++ b/apps/contacts/js/jquery.combobox.js @@ -72,17 +72,10 @@ .appendTo( ul ); }; - this.button = $( "" ) + /*this.button = $( "" ) .attr( "tabIndex", -1 ) .attr( "title", "Show All Items" ) .insertAfter( input ) - /*.button({ - icons: { - primary: "ui-icon-triangle-1-s" - }, - text: false - }) - .removeClass( "ui-corner-all" )*/ .addClass('svg') .addClass('action') .addClass('combo-button') @@ -99,7 +92,7 @@ // pass empty string as value to search for, displaying all results input.autocomplete( "search", "" ); input.focus(); - }); + });*/ $.each(this.options, function(key, value) { self._setOption(key, value); }); @@ -123,17 +116,23 @@ case "id": this.options['id'] = value; this.input.attr('id', value); - break; + break; case "name": this.options['name'] = value; this.input.attr('name', value); - break; + break; + case "attributes": + var input = this.input; + $.each(this.options['attributes'], function(key, value) { + input.attr(key, value); + }); + break; case "classes": var input = this.input; $.each(this.options['classes'], function(key, value) { input.addClass(value); }); - break; + break; } // In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget $.Widget.prototype._setOption.apply( this, arguments ); diff --git a/apps/contacts/js/jquery.multi-autocomplete.js b/apps/contacts/js/jquery.multi-autocomplete.js index 7607de3f91..e1c5d63dc5 100644 --- a/apps/contacts/js/jquery.multi-autocomplete.js +++ b/apps/contacts/js/jquery.multi-autocomplete.js @@ -62,7 +62,7 @@ return false; } }); - this.button = $( "" ) + /*this.button = $( "" ) .attr( "tabIndex", -1 ) .attr( "title", "Show All Items" ) .insertAfter( this.element ) @@ -86,7 +86,7 @@ // pass empty string as value to search for, displaying all results self.element.autocomplete( "search", "" ); self.element.focus(); - }); + });*/ }, }); })( jQuery ); diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php index d243c2b5e1..961ce693e6 100644 --- a/apps/contacts/templates/part.contact.php +++ b/apps/contacts/templates/part.contact.php @@ -21,12 +21,12 @@ $id = isset($_['id']) ? $_['id'] : ''; -
+
-
+ +
+ -
-
+
-
- -
-
- -
+ + + + +
- + - + - - - + + +
-
- +
+
+
+ + +
+
+
+
From fc555b48ec0f5600a7f9ae25354ffaca2e0533de Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 3 Apr 2012 07:29:47 +0200 Subject: [PATCH 22/37] Contacts: Added autocomplete using geonames.org. --- apps/contacts/css/contacts.css | 1 + apps/contacts/js/contacts.js | 88 +++++++++++++++++++++++++++- apps/contacts/templates/settings.php | 1 + 3 files changed, 87 insertions(+), 3 deletions(-) diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 9d238c36f3..4e7d8c285a 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -28,6 +28,7 @@ dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } .form dd { display: table-cell; clear: right; float: left; margin: 0; padding: 0px; white-space: nowrap; vertical-align: text-bottom; } .loading { background: url('../../../core/img/loading.gif') no-repeat center !important; /*cursor: progress; */ cursor: wait; } +.ui-autocomplete-loading { background: url('../../../core/img/loading.gif') right center no-repeat; } .float { float: left; } .listactions { height: 1em; width:60px; float: left; clear: right; } .add,.edit,.delete,.mail, .globe { cursor: pointer; width: 20px; height: 20px; margin: 0; float: left; position:relative; display: none; } diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index e838d713d4..b72f3c9a67 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -908,10 +908,92 @@ Contacts={ container.remove(); } //Contacts.UI.showHideContactInfo(); - }/*, + }, open : function(event, ui) { - // load 'ADR' property - maybe :-P - }*/ + $( "#adr_city" ).autocomplete({ + source: function( request, response ) { + $.ajax({ + url: "http://ws.geonames.org/searchJSON", + dataType: "jsonp", + data: { + featureClass: "P", + style: "full", + maxRows: 12, + name_startsWith: request.term + }, + success: function( data ) { + response( $.map( data.geonames, function( item ) { + /*for(var key in item) { + console.log(key + ': ' + item[key]); + }*/ + return { + label: item.name + (item.adminName1 ? ", " + item.adminName1 : "") + ", " + item.countryName, + value: item.name, + country: item.countryName + } + })); + } + }); + }, + minLength: 2, + select: function( event, ui ) { + if(ui.item) { + $('#adr_country').val(ui.item.country); + } + /*log( ui.item ? + "Selected: " + ui.item.label : + "Nothing selected, input was " + this.value);*/ + }, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } + }); + $( "#adr_country" ).autocomplete({ + source: function( request, response ) { + $.ajax({ + url: "http://ws.geonames.org/searchJSON", + dataType: "jsonp", + data: { + /*featureClass: "A",*/ + featureCode: "PCLI", + /*countryBias: "true",*/ + /*style: "full",*/ + maxRows: 12, + name_startsWith: request.term + }, + success: function( data ) { + response( $.map( data.geonames, function( item ) { + for(var key in item) { + console.log(key + ': ' + item[key]); + } + return { + label: item.name, + value: item.name + } + })); + } + }); + }, + minLength: 2, + select: function( event, ui ) { + /*if(ui.item) { + $('#adr_country').val(ui.item.country); + } + log( ui.item ? + "Selected: " + ui.item.label : + "Nothing selected, input was " + this.value);*/ + }, + open: function() { + $( this ).removeClass( "ui-corner-all" ).addClass( "ui-corner-top" ); + }, + close: function() { + $( this ).removeClass( "ui-corner-top" ).addClass( "ui-corner-all" ); + } + }); + } }); } else { alert(jsondata.data.message); diff --git a/apps/contacts/templates/settings.php b/apps/contacts/templates/settings.php index f56de0ec8b..d77c4d3802 100644 --- a/apps/contacts/templates/settings.php +++ b/apps/contacts/templates/settings.php @@ -9,4 +9,5 @@
/principals//
+ Powered by geonames.org webservice From dd4e577f6db422aed3d528d12a8e77de9c3cfaef Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 3 Apr 2012 08:13:10 +0200 Subject: [PATCH 23/37] Contacts: l11n for geo autocomplete. Not sure if it works though. --- apps/contacts/js/contacts.js | 4 +++- apps/contacts/templates/index.php | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index b72f3c9a67..cc4da5837e 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -919,6 +919,7 @@ Contacts={ featureClass: "P", style: "full", maxRows: 12, + lang: lang, name_startsWith: request.term }, success: function( data ) { @@ -937,7 +938,7 @@ Contacts={ }, minLength: 2, select: function( event, ui ) { - if(ui.item) { + if(ui.item && $('#adr_country').val().trim().length == 0) { $('#adr_country').val(ui.item.country); } /*log( ui.item ? @@ -961,6 +962,7 @@ Contacts={ featureCode: "PCLI", /*countryBias: "true",*/ /*style: "full",*/ + lang: lang, maxRows: 12, name_startsWith: request.term }, diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index af159ce9c6..d68dd68f60 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -1,6 +1,7 @@
From cd05dfb9430da93f2584d928ef963c625562c8fa Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Tue, 3 Apr 2012 22:17:34 +0200 Subject: [PATCH 24/37] adding icons to filepicker --- core/js/oc-dialogs.js | 2 +- files/ajax/rawlist.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index d40c433bda..7ae9bc9d2a 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -204,7 +204,7 @@ OCdialogs = { var entry_template = '
*NAME*
*LASTMODDATE*
'; 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*', OC.webroot+'/core/img/filetypes/'+(r.data[a].type=='dir'?'folder':r.data[a].mimetype.replace('/','-'))+'.png').replace('*ENTRYNAME*', r.data[a].name).replace('*ENTRYTYPE*', r.data[a].type); + 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); } $(dialog_content_id + ' #filelist').html(names); }, diff --git a/files/ajax/rawlist.php b/files/ajax/rawlist.php index 0abe81e672..88ba48a6c4 100644 --- a/files/ajax/rawlist.php +++ b/files/ajax/rawlist.php @@ -5,6 +5,7 @@ $RUNTIME_APPTYPES=array('filesystem'); // Init owncloud require_once('../../lib/base.php'); +require_once('../../lib/template.php'); OC_JSON::checkLoggedIn(); @@ -15,6 +16,7 @@ $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; $files = array(); foreach( OC_Files::getdirectorycontent( $dir ) as $i ){ $i["date"] = OC_Util::formatDate($i["mtime"] ); + $i['mimetype_icon'] = $i['type'] == 'dir' ? mimetype_icon('dir'): mimetype_icon($i['mimetype']); $files[] = $i; } From 95c2ac5d585bfd1106b173c00b4c29719c08b25f Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Tue, 3 Apr 2012 21:14:55 +0000 Subject: [PATCH 25/37] Dont typecast variables as integers --- core/lostpassword/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lostpassword/index.php b/core/lostpassword/index.php index da0428e3ce..9529c0c957 100644 --- a/core/lostpassword/index.php +++ b/core/lostpassword/index.php @@ -12,7 +12,7 @@ require_once('../../lib/base.php'); // Someone lost their password: if (isset($_POST['user'])) { if (OC_User::userExists($_POST['user'])) { - $token = sha1($_POST['user']+uniqId()); + $token = sha1($_POST['user'].uniqId()); OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token); $email = OC_Preferences::getValue($_POST['user'], 'settings', 'email', ''); if (!empty($email)) { From acdce2b1e01f7c0a77b7e7949540e1b0ba94efd1 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Tue, 3 Apr 2012 22:31:34 +0000 Subject: [PATCH 26/37] Check blacklist before saving to filesystem --- lib/base.php | 3 +++ lib/filesystem.php | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/base.php b/lib/base.php index a4a94e8696..83dd0c98f4 100644 --- a/lib/base.php +++ b/lib/base.php @@ -365,6 +365,9 @@ class OC{ OC_App::loadApps(); } } + + // Check for blacklisted files + OC_Hook::connect('OC_Filesystem','write','OC_Filesystem','isBlacklisted'); //make sure temporary files are cleaned up register_shutdown_function(array('OC_Helper','cleanTmp')); diff --git a/lib/filesystem.php b/lib/filesystem.php index 12905d189f..b6909f5acd 100644 --- a/lib/filesystem.php +++ b/lib/filesystem.php @@ -298,6 +298,19 @@ class OC_Filesystem{ } return true; } + + /** + * checks if a file is blacklsited for storage in the filesystem + * @param array $data from hook + */ + static public function isBlacklisted($data){ + $blacklist = array('.htaccess'); + $filename = strtolower(basename($data['path'])); + if(in_array($filename,$blacklist)){ + $data['run'] = false; + } + } + /** * following functions are equivilent to their php buildin equivilents for arguments/return values. */ From 60e3b563e26478eab257413b5cac9b3f619570ac Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 4 Apr 2012 12:41:32 +0200 Subject: [PATCH 27/37] webdav needs to load authentication apps --- apps/user_ldap/appinfo/info.xml | 3 +++ apps/user_openid/appinfo/info.xml | 3 +++ files/webdav.php | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/user_ldap/appinfo/info.xml b/apps/user_ldap/appinfo/info.xml index 9a6ee1436f..99830dd1ff 100644 --- a/apps/user_ldap/appinfo/info.xml +++ b/apps/user_ldap/appinfo/info.xml @@ -7,4 +7,7 @@ AGPL Dominik Schmidt 2 + + + diff --git a/apps/user_openid/appinfo/info.xml b/apps/user_openid/appinfo/info.xml index 37be15abfd..721db1877e 100644 --- a/apps/user_openid/appinfo/info.xml +++ b/apps/user_openid/appinfo/info.xml @@ -7,4 +7,7 @@ AGPL Robin Appelman 2 + + + diff --git a/files/webdav.php b/files/webdav.php index 1120973787..25e3302447 100644 --- a/files/webdav.php +++ b/files/webdav.php @@ -27,7 +27,7 @@ $RUNTIME_NOSETUPFS = true; // only need filesystem apps -$RUNTIME_APPTYPES=array('filesystem'); +$RUNTIME_APPTYPES=array('filesystem','authentication'); require_once('../lib/base.php'); From 85f9869f6925ef52c1015916bbc28e13c15abc73 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Wed, 4 Apr 2012 13:17:03 +0000 Subject: [PATCH 28/37] Make the token really random --- core/lostpassword/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lostpassword/index.php b/core/lostpassword/index.php index 9529c0c957..a9b7d10804 100644 --- a/core/lostpassword/index.php +++ b/core/lostpassword/index.php @@ -12,7 +12,7 @@ require_once('../../lib/base.php'); // Someone lost their password: if (isset($_POST['user'])) { if (OC_User::userExists($_POST['user'])) { - $token = sha1($_POST['user'].uniqId()); + $token = sha1($_POST['user'].md5(uniqid(rand(), true))); OC_Preferences::setValue($_POST['user'], 'owncloud', 'lostpassword', $token); $email = OC_Preferences::getValue($_POST['user'], 'settings', 'email', ''); if (!empty($email)) { From 5b4a30367235a27f21d44b98eaae953e1cec1eac Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Thu, 5 Apr 2012 21:29:54 +0200 Subject: [PATCH 29/37] loading screen for filepicker --- core/css/styles.css | 1 + core/js/oc-dialogs.js | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/css/styles.css b/core/css/styles.css index 1c50df9e58..0eb299a899 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -137,3 +137,4 @@ a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padd #dirtree {width: 100%;} #filelist {height: 270px; overflow:scroll; background-color: white;} .filepicker_element_selected { background-color: lightblue;} +.filepicker_loader {height: 270px; width: 100%; background-color: #333; opacity: 0.3; visibility: visible; position:absolute; top:0; left:0; text-align:center; padding-top: 150px;} diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index 7ae9bc9d2a..e027ffb510 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -100,7 +100,7 @@ OCdialogs = { filepicker:function(title, callback, multiselect, mimetype_filter, modal) { var c_name = 'oc-dialog-'+OCdialogs.dialogs_counter+'-content'; var c_id = '#'+c_name; - var d = '
'; + var d = '
'; if (!modal) modal = false; if (!multiselect) multiselect = false; $('body').append(d); @@ -207,6 +207,7 @@ OCdialogs = { 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); } $(dialog_content_id + ' #filelist').html(names); + $(dialog_content_id + ' .filepicker_loader').css('visibility', 'hidden'); }, handleTreeListSelect:function(event) { var newval = parseInt($(this).val()); @@ -220,6 +221,7 @@ OCdialogs = { var path = ''; $(this).children().each(function(i, element) { if (skip_first) {skip_first = false; return; }path += '/'+$(element).text(); }); $(event.data.dcid).data('path', path); + $(event.data.dcid + ' .filepicker_loader').css('visibility', 'visible'); $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)}); }, // this function is in early development state, please dont use it unlsess you know what you are doing @@ -237,6 +239,7 @@ OCdialogs = { $(dcid + ' #dirtree option:last').removeAttr('selected'); var newval = parseInt($(dcid + ' #dirtree option:last').val())+1; $(dcid + ' #dirtree').append(''); + $(dcid + ' .filepicker_loader').css('visibility', 'visible'); $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: p}, function(r){OC.dialogs.fillFilePicker(r, dcid)}); } }; From fe3d3be399f7b64b3f81c4f8fcd932b2d810ee45 Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Thu, 5 Apr 2012 22:25:58 +0200 Subject: [PATCH 30/37] filepicker loading style fixup --- core/css/styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/css/styles.css b/core/css/styles.css index 0eb299a899..9d9f6d9830 100644 --- a/core/css/styles.css +++ b/core/css/styles.css @@ -137,4 +137,4 @@ a.bookmarklet { background-color: #ddd; border:1px solid #ccc; padding: 5px;padd #dirtree {width: 100%;} #filelist {height: 270px; overflow:scroll; background-color: white;} .filepicker_element_selected { background-color: lightblue;} -.filepicker_loader {height: 270px; width: 100%; background-color: #333; opacity: 0.3; visibility: visible; position:absolute; top:0; left:0; text-align:center; padding-top: 150px;} +.filepicker_loader {height: 120px; width: 100%; background-color: #333; opacity: 0.3; visibility: visible; position:absolute; top:0; left:0; text-align:center; padding-top: 150px;} From 96c99125da5fe74d4a8fa329869cca7f775805cf Mon Sep 17 00:00:00 2001 From: Bartek Przybylski Date: Thu, 5 Apr 2012 23:18:44 +0200 Subject: [PATCH 31/37] mimetype filter for filepicker --- core/js/oc-dialogs.js | 8 ++++---- files/ajax/rawlist.php | 3 ++- lib/filecache.php | 6 +++--- lib/files.php | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js index e027ffb510..a3aa1e8c14 100644 --- a/core/js/oc-dialogs.js +++ b/core/js/oc-dialogs.js @@ -107,8 +107,8 @@ OCdialogs = { $(c_id + ' #dirtree').focus(function() { var t = $(this); t.data('oldval', t.val())}) .change({dcid: c_id}, OC.dialogs.handleTreeListSelect); $(c_id).ready(function(){ - $.getJSON(OC.webroot+'/files/ajax/rawlist.php', function(r){OC.dialogs.fillFilePicker(r, c_id, callback)}); - }).data('multiselect', multiselect); + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {mimetype: mimetype_filter} ,function(r){OC.dialogs.fillFilePicker(r, c_id, callback)}); + }).data('multiselect', multiselect).data('mimetype',mimetype_filter); // build buttons var b = [ {text: t('dialogs', 'Choose'), click: function(){ @@ -222,7 +222,7 @@ OCdialogs = { $(this).children().each(function(i, element) { if (skip_first) {skip_first = false; return; }path += '/'+$(element).text(); }); $(event.data.dcid).data('path', path); $(event.data.dcid + ' .filepicker_loader').css('visibility', 'visible'); - $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)}); + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: path, mimetype: $(event.data.dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, event.data.dcid)}); }, // this function is in early development state, please dont use it unlsess you know what you are doing handlePickerClick:function(element, name, dcid) { @@ -240,6 +240,6 @@ OCdialogs = { var newval = parseInt($(dcid + ' #dirtree option:last').val())+1; $(dcid + ' #dirtree').append(''); $(dcid + ' .filepicker_loader').css('visibility', 'visible'); - $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: p}, function(r){OC.dialogs.fillFilePicker(r, dcid)}); + $.getJSON(OC.webroot+'/files/ajax/rawlist.php', {dir: p, mimetype: $(dcid).data('mimetype')}, function(r){OC.dialogs.fillFilePicker(r, dcid)}); } }; diff --git a/files/ajax/rawlist.php b/files/ajax/rawlist.php index 88ba48a6c4..e02c5b6273 100644 --- a/files/ajax/rawlist.php +++ b/files/ajax/rawlist.php @@ -11,10 +11,11 @@ OC_JSON::checkLoggedIn(); // Load the files $dir = isset( $_GET['dir'] ) ? $_GET['dir'] : ''; +$mimetype = isset($_GET['mimetype']) ? $_GET['mimetype'] : ''; // make filelist $files = array(); -foreach( OC_Files::getdirectorycontent( $dir ) as $i ){ +foreach( OC_Files::getdirectorycontent( $dir, $mimetype ) as $i ){ $i["date"] = OC_Util::formatDate($i["mtime"] ); $i['mimetype_icon'] = $i['type'] == 'dir' ? mimetype_icon('dir'): mimetype_icon($i['mimetype']); $files[] = $i; diff --git a/lib/filecache.php b/lib/filecache.php index 4a4183cbdb..cdd91dcbfa 100644 --- a/lib/filecache.php +++ b/lib/filecache.php @@ -240,7 +240,7 @@ class OC_FileCache{ * - encrypted * - versioned */ - public static function getFolderContent($path,$root=''){ + public static function getFolderContent($path,$root='',$mimetype_filter=''){ if(self::isUpdated($path,$root)){ self::updateFolder($path,$root); } @@ -252,8 +252,8 @@ class OC_FileCache{ } $path=$root.$path; $parent=self::getFileId($path); - $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=?'); - $result=$query->execute(array($parent))->fetchAll(); + $query=OC_DB::prepare('SELECT name,ctime,mtime,mimetype,size,encrypted,versioned,writable FROM *PREFIX*fscache WHERE parent=? AND (mimetype LIKE ? OR mimetype = ?)'); + $result=$query->execute(array($parent, $mimetype_filter.'%', 'httpd/unix-directory'))->fetchAll(); if(is_array($result)){ return $result; }else{ diff --git a/lib/files.php b/lib/files.php index e7bfbbc19b..a68c29ad98 100644 --- a/lib/files.php +++ b/lib/files.php @@ -32,11 +32,11 @@ class OC_Files { * get the content of a directory * @param dir $directory */ - public static function getDirectoryContent($directory){ + public static function getDirectoryContent($directory, $mimetype_filter = ''){ if(strpos($directory,OC::$CONFIG_DATADIRECTORY)===0){ $directory=substr($directory,strlen(OC::$CONFIG_DATADIRECTORY)); } - $files=OC_FileCache::getFolderContent($directory); + $files=OC_FileCache::getFolderContent($directory, '', $mimetype_filter); foreach($files as &$file){ $file['directory']=$directory; $file['type']=($file['mimetype']=='httpd/unix-directory')?'dir':'file'; From 22466010fc8d5a7d5cad876b8603f2bffee58182 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Fri, 6 Apr 2012 21:37:28 +0000 Subject: [PATCH 32/37] Provide undo when closing editor with unsaved changes --- apps/files_texteditor/js/editor.js | 100 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 1e136fe68e..3d98a91c05 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -76,7 +76,7 @@ function showControls(filename,writeperms){ function bindControlEvents(){ $("#editor_save").die('click',doFileSave).live('click',doFileSave); - $('#editor_close').die('click',closeBtnClick).live('click',closeBtnClick); + $('#editor_close').die('click',hideFileEditor).live('click',hideFileEditor); $('#gotolineval').die('keyup', goToLine).live('keyup', goToLine); $('#editorsearchval').die('keyup', doSearch).live('keyup', doSearch); $('#clearsearchbtn').die('click', resetSearch).live('click', resetSearch); @@ -183,6 +183,8 @@ function giveEditorFocus(){ // Loads the file editor. Accepts two parameters, dir and filename. function showFileEditor(dir,filename){ + // Delete any old editors + $('#editor').remove(); if(!editorIsShown()){ // Loads the file editor and display it. $('#content').append('
'); @@ -235,52 +237,56 @@ function showFileEditor(dir,filename){ } } -function closeBtnClick(){ - if($('#editor').attr('data-edited')=='true'){ - // Show confirm - OC.dialogs.confirm(t('files_texteditor','You have unsaved changes that will be lost! Do you still want to close?'),t('files_texteditor','Really close?'),function(close){ - if(close){ - hideFileEditor(); - } - }); - } else { - hideFileEditor(); - } -} - // Fades out the editor. function hideFileEditor(){ - // Fades out editor controls - $('#editorcontrols').fadeOut('slow',function(){ - $(this).remove(); - $(".crumb:last").addClass('last'); - }); - // Fade out editor - $('#editor').fadeOut('slow', function(){ - $(this).remove(); - // Reset document title - document.title = "ownCloud"; - var editorhtml = '
'; - $('table').after(editorhtml); - $('.actions,#file_access_panel').fadeIn('slow'); - $('table').fadeIn('slow'); - }); - is_editor_shown = false; + if($('#editor').attr('data-edited') == 'true'){ + // Hide, not remove + $('#editorcontrols').fadeOut('slow',function(){ + // Check if there is a folder in the breadcrumb + if($('.crumb.ui-droppable').length){ + $('.crumb.ui-droppable:last').addClass('last'); + } + }); + // Fade out editor + $('#editor').fadeOut('slow', function(){ + // Reset document title + document.title = "ownCloud"; + $('.actions,#file_access_panel').fadeIn('slow'); + $('table').fadeIn('slow'); + }); + $('#notification').text(t('files_texteditor','There were unsaved changes, click here to go back')); + $('#notification').data('reopeneditor',true); + $('#notification').fadeIn(); + is_editor_shown = false; + } else { + // Remove editor + $('#editorcontrols').fadeOut('slow',function(){ + $(this).remove(); + $(".crumb:last").addClass('last'); + }); + // Fade out editor + $('#editor').fadeOut('slow', function(){ + $(this).remove(); + // Reset document title + document.title = "ownCloud"; + $('.actions,#file_access_panel').fadeIn('slow'); + $('table').fadeIn('slow'); + }); + is_editor_shown = false; + } } -// Keyboard Shortcuts -var ctrlBtn = false; +// Reopens the last document +function reopenEditor(){ + $('.actions,#file_action_panel').fadeOut('slow'); + $('table').fadeOut('slow', function(){ + $('#controls .last').not('#breadcrumb_file').removeClass('last'); + $('#editor').fadeIn('fast'); + $('#editorcontrols').fadeIn('fast', function(){ -// TODO fix detection of ctrl keyup -// returns true if ctrl+s or cmd+s is being pressed -function checkForSaveKeyPress(e){ - if(e.which == 17 || e.which == 91) ctrlBtn=true; - if(e.which == 83 && ctrlBtn == true) { - e.preventDefault(); - $('#editor_save').trigger('click'); - return false; - - } + }); + }); + is_editor_shown = true; } // resizes the editor window @@ -313,7 +319,11 @@ $(document).ready(function(){ // Binds the file save and close editor events, and gotoline button bindControlEvents(); $('#editor').remove(); - // Binds the save keyboard shortcut events - //$(document).unbind('keydown').bind('keydown',checkForSaveKeyPress); - + $('#notification').click(function(){ + if($('#notification').data('reopeneditor')) + { + reopenEditor(); + } + $('#notification').fadeOut(); + }); }); From a098c7c6858a7c2c646e38d1ba150b13821f4085 Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Fri, 6 Apr 2012 21:38:38 +0000 Subject: [PATCH 33/37] Give editor focus after saving --- apps/files_texteditor/js/editor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 3d98a91c05..016632c997 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -174,6 +174,7 @@ function doFileSave(){ },'json'); } } + giveEditorFocus(); }; // Gives the editor focus From 42e110b49cc2efa63a46f39289f1bfb3e7dbca6f Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Sat, 7 Apr 2012 13:07:44 +0000 Subject: [PATCH 34/37] Update url --- settings/templates/apps.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/templates/apps.php b/settings/templates/apps.php index 27133e9e67..1e49b4c892 100644 --- a/settings/templates/apps.php +++ b/settings/templates/apps.php @@ -5,7 +5,7 @@ */?>
    From 660951dc64087e7ebedaad5c0ae1104d8dd4d0cf Mon Sep 17 00:00:00 2001 From: Tom Needham Date: Sat, 7 Apr 2012 13:32:00 +0000 Subject: [PATCH 35/37] Add some filetypes --- apps/files_texteditor/js/editor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/files_texteditor/js/editor.js b/apps/files_texteditor/js/editor.js index 016632c997..bc8a20408c 100644 --- a/apps/files_texteditor/js/editor.js +++ b/apps/files_texteditor/js/editor.js @@ -22,9 +22,11 @@ function setSyntaxMode(ext){ filetype["css"] = "css"; filetype["groovy"] = "groovy"; filetype["haxe"] = "hx"; + filetype["htm"] = "html"; filetype["html"] = "html"; filetype["java"] = "java"; filetype["js"] = "javascript"; + filetype["jsm"] = "javascript"; filetype["json"] = "json"; filetype["latex"] = "latex"; filetype["ly"] = "latex"; From b71cf1a4f97bb660a279a16ca4da864b56986a59 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 7 Apr 2012 16:01:50 +0200 Subject: [PATCH 36/37] Fix bug oc-413: PHP fatal error in contacts page when no contacts in ownCloud. --- apps/contacts/index.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/apps/contacts/index.php b/apps/contacts/index.php index 076b10c2ee..776c57ca60 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -43,17 +43,15 @@ if(count($categories) == 0) { $vcaddressbookids[] = $vcaddressbook['id']; } $vccontacts = OC_Contacts_VCard::all($vcaddressbookids); - if(count($vccontacts) == 0) { - bailOut(OC_Contacts_App::$l10n->t('No contacts found.')); + if(count($vccontacts) > 0) { + $cards = array(); + foreach($vccontacts as $vccontact) { + $cards[] = $vccontact['carddata']; + } + + OC_Contacts_App::$categories->rescan($cards); + $categories = OC_Contacts_App::$categories->categories(); } - - $cards = array(); - foreach($vccontacts as $vccontact) { - $cards[] = $vccontact['carddata']; - } - - OC_Contacts_App::$categories->rescan($cards); - $categories = OC_Contacts_App::$categories->categories(); } } From d1ae6512cc760c76798a5a8636d1d7908c706ae8 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 7 Apr 2012 16:03:11 +0200 Subject: [PATCH 37/37] Contacts: Misc. cleanup tweaks. --- apps/contacts/ajax/saveproperty.php | 58 +++++++++---------- apps/contacts/css/contacts.css | 11 ++-- apps/contacts/js/contacts.js | 29 +++------- apps/contacts/templates/part.contact.php | 19 +++--- .../templates/part.edit_address_dialog.php | 14 ++--- apps/contacts/templates/settings.php | 2 +- core/js/oc-vcategories.js | 4 +- 7 files changed, 64 insertions(+), 73 deletions(-) diff --git a/apps/contacts/ajax/saveproperty.php b/apps/contacts/ajax/saveproperty.php index 924d873652..4cef4d1e7a 100644 --- a/apps/contacts/ajax/saveproperty.php +++ b/apps/contacts/ajax/saveproperty.php @@ -97,39 +97,39 @@ switch($element) { } break; case 'CATEGORIES': - /* multi autocomplete triggers an save with empty value */ + /* multi autocomplete triggers an save with empty value if (!$value) { $value = $vcard->getAsString('CATEGORIES'); } - break; + break;*/ case 'EMAIL': $value = strtolower($value); break; } if(!$value) { - bailOut(OC_Contacts_App::$l10n->t('Cannot save empty value.')); -} - -/* setting value */ -switch($element) { - case 'BDAY': - case 'FN': - case 'N': - case 'ORG': - case 'NOTE': - case 'NICKNAME': - case 'CATEGORIES': - debug('Setting string:'.$name.' '.$value); - $vcard->setString($name, $value); - break; - case 'EMAIL': - case 'TEL': - case 'ADR': // should I delete the property if empty or throw an error? - debug('Setting element: (EMAIL/TEL/ADR)'.$element); - if(!$value) { - unset($vcard->children[$line]); // Should never happen... - } else { + unset($vcard->children[$line]); + $checksum = ''; +} else { + /* setting value */ + switch($element) { + case 'BDAY': + case 'FN': + case 'N': + case 'ORG': + case 'NOTE': + case 'NICKNAME': + debug('Setting string:'.$name.' '.$value); + $vcard->setString($name, $value); + break; + case 'CATEGORIES': + debug('Setting string:'.$name.' '.$value); + $vcard->children[$line]->setValue($value); + break; + case 'EMAIL': + case 'TEL': + case 'ADR': // should I delete the property if empty or throw an error? + debug('Setting element: (EMAIL/TEL/ADR)'.$element); $vcard->children[$line]->setValue($value); $vcard->children[$line]->parameters = array(); if(!is_null($parameters)) { @@ -142,12 +142,12 @@ switch($element) { } } } - } - break; + break; + } + // Do checksum and be happy + $checksum = md5($vcard->children[$line]->serialize()); } -// Do checksum and be happy -$checksum = md5($vcard->children[$line]->serialize()); -debug('New checksum: '.$checksum); +//debug('New checksum: '.$checksum); if(!OC_Contacts_VCard::edit($id,$vcard)) { bailOut(OC_Contacts_App::$l10n->t('Error updating contact property.')); diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 4e7d8c285a..5d3ebf65fb 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -13,19 +13,22 @@ #contacts_propertymenu li a { padding: 3px; display: block } #contacts_propertymenu li:hover { background-color: #1d2d44; } #contacts_propertymenu li a:hover { color: #fff } -#actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0;} +#actionbar { height: 30px; width: 200px; position: fixed; right: 0px; top: 75px; margin: 0 0 0 0; padding: 0 0 0 0; z-index: 1000; } #card { width: auto;/*max-width: 70em; border: thin solid lightgray; display: block;*/ } #firstrun { width: 100%; position: absolute; top: 5em; left: 0; text-align: center; font-weight:bold; font-size:1.5em; color:#777; } #firstrun #selections { font-size:0.8em; margin: 2em auto auto auto; clear: both; } #card input[type="text"].contacts_property,input[type="email"].contacts_property { width: 14em; float: left; } .categories { float: left; width: 16em; } -#card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select { background-color: #fefefe; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; } -#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } -input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid { color: #bbb !important; } +#card input[type="text"],input[type="email"],input[type="tel"],input[type="date"], select, textarea { background-color: #fefefe; border: 0 !important; -webkit-appearance:none !important; -moz-appearance:none !important; -webkit-box-sizing:none !important; -moz-box-sizing:none !important; box-sizing:none !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; -moz-border-radius: 0px; -webkit-border-radius: 0px; border-radius: 0px; float: left; } +#card input[type="text"]:hover, input[type="text"]:focus, input[type="text"]:active,input[type="email"]:hover,input[type="tel"]:hover,input[type="date"]:hover,input[type="date"],input[type="date"]:hover,input[type="date"]:active,input[type="date"]:active,input[type="date"]:active,input[type="email"]:active,input[type="tel"]:active, select:hover, select:focus, select:active, textarea:focus, textarea:hover { border: 0 !important; -webkit-appearance:textfield; -moz-appearance:textfield; -webkit-box-sizing:content-box; -moz-box-sizing:content-box; box-sizing:content-box; background:#fff; color:#333; border:1px solid #ddd; -moz-box-shadow:0 1px 1px #fff, 0 2px 0 #bbb inset; -webkit-box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; box-shadow:0 1px 1px #fff, 0 1px 0 #bbb inset; -moz-border-radius:.5em; -webkit-border-radius:.5em; border-radius:.5em; outline:none; float: left; } +input[type="text"]:invalid,input[type="email"]:invalid,input[type="tel"]:invalid,input[type="date"]:invalid, textarea:invalid { color: #bbb !important; } +textarea { min-height: 4em; } dl.form { width: 100%; float: left; clear: right; margin: 0; padding: 0; } .form dt { display: table-cell; clear: left; float: left; width: 7em; margin: 0; padding: 0.8em 0.5em 0 0; text-align:right; text-overflow:ellipsis; o-text-overflow: ellipsis; vertical-align: text-bottom; color: #bbb;/* white-space: pre-wrap; white-space: -moz-pre-wrap !important; white-space: -pre-wrap; white-space: -o-pre-wrap;*/ } .form dd { display: table-cell; clear: right; float: left; margin: 0; padding: 0px; white-space: nowrap; vertical-align: text-bottom; } +#address.form dt { min-width: 5em; } +#address.form dl { min-width: 10em; } .loading { background: url('../../../core/img/loading.gif') no-repeat center !important; /*cursor: progress; */ cursor: wait; } .ui-autocomplete-loading { background: url('../../../core/img/loading.gif') right center no-repeat; } diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index cc4da5837e..3b264c0197 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -116,7 +116,7 @@ Contacts={ }, loadListHandlers:function() { //$('.add,.delete').hide(); - $('.globe,.mail,.delete,.edit').tipsy(); + $('.globe,.mail,.delete,.edit,.tip').tipsy(); $('.addresscard,.propertylist li,.propertycontainer').hover( function () { $(this).find('.globe,.mail,.delete,.edit').fadeIn(100); @@ -171,10 +171,6 @@ Contacts={ // Contacts.UI.Card.editAddress(); // return false; // }); - $('#n').click(function(){ - Contacts.UI.Card.editName(); - //return false; - }); $('#edit_name').click(function(){ Contacts.UI.Card.editName(); return false; @@ -258,12 +254,12 @@ Contacts={ }); } }, - export:function() { + do_export:function() { document.location.href = OC.linkTo('contacts', 'export.php') + '?contactid=' + this.id; //$.get(OC.linkTo('contacts', 'export.php'),{'contactid':this.id},function(jsondata){ //}); }, - import:function(){ + do_import:function(){ Contacts.UI.notImplemented(); }, add:function(n, fn, aid, isnew){ // add a new contact @@ -293,11 +289,11 @@ Contacts={ if(isnew) { Contacts.UI.Card.addProperty('EMAIL'); Contacts.UI.Card.addProperty('TEL'); - Contacts.UI.Card.addProperty('BDAY'); Contacts.UI.Card.addProperty('NICKNAME'); Contacts.UI.Card.addProperty('ORG'); Contacts.UI.Card.addProperty('CATEGORIES'); $('#fn').focus(); + $('#fn').select(); } } else{ @@ -315,7 +311,7 @@ Contacts={ } }); }, - delete:function() { + do_delete:function() { $('#contacts_deletecard').tipsy('hide'); OC.dialogs.confirm(t('contacts', 'Are you sure you want to delete this contact?'), t('contacts', 'Warning'), function(answer) { if(answer == true) { @@ -1256,7 +1252,7 @@ Contacts={ }); } }, - import:function(){ + do_import:function(){ Contacts.UI.notImplemented(); }, submit:function(button, bookid){ @@ -1289,9 +1285,7 @@ Contacts={ } }, Contacts:{ - /** - * Reload the contacts list. - */ + // Reload the contacts list. update:function(){ console.log('Contacts.update, start'); $.getJSON('ajax/contacts.php',{},function(jsondata){ @@ -1306,9 +1300,7 @@ Contacts={ }); setTimeout(Contacts.UI.Contacts.lazyupdate, 500); }, - /** - * Add thumbnails to the contact list as they become visible in the viewport. - */ + // Add thumbnails to the contact list as they become visible in the viewport. lazyupdate:function(){ $('#contacts li').live('inview', function(){ if (!$(this).find('a').attr('style')) { @@ -1328,9 +1320,6 @@ $(document).ready(function(){ OCCategories.changed = Contacts.UI.Card.categoriesChanged; OCCategories.app = 'contacts'; - /** - * Show the Addressbook chooser - */ $('#chooseaddressbook').click(function(){ Contacts.UI.Addressbooks.overview(); return false; @@ -1363,7 +1352,7 @@ $(document).ready(function(){ }); $('#contacts_deletecard').live('click',function(){ - Contacts.UI.Card.delete(); + Contacts.UI.Card.do_delete(); }); $('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) { diff --git a/apps/contacts/templates/part.contact.php b/apps/contacts/templates/part.contact.php index 961ce693e6..03d2fad853 100644 --- a/apps/contacts/templates/part.contact.php +++ b/apps/contacts/templates/part.contact.php @@ -17,7 +17,7 @@ $id = isset($_['id']) ? $_['id'] : '';
  • t('Categories'); ?>
- + @@ -37,7 +37,7 @@ $id = isset($_['id']) ? $_['id'] : ''; - +
@@ -62,7 +62,7 @@ $id = isset($_['id']) ? $_['id'] : '';
-
+
@@ -73,7 +73,7 @@ $id = isset($_['id']) ? $_['id'] : '';
@@ -85,7 +85,7 @@ $id = isset($_['id']) ? $_['id'] : '';
@@ -131,7 +130,7 @@ $(document).ready(function(){ Contacts.UI.Card.loadContact(jsondata.data); } else{ - Contacts.UI.messageBox(t('contacts', 'Error'), jsondata.data.message); + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); } }); } diff --git a/apps/contacts/templates/part.edit_address_dialog.php b/apps/contacts/templates/part.edit_address_dialog.php index 0ecdc4e191..507a3acaa0 100644 --- a/apps/contacts/templates/part.edit_address_dialog.php +++ b/apps/contacts/templates/part.edit_address_dialog.php @@ -22,44 +22,44 @@ foreach(isset($adr['parameters']['TYPE'])?array($adr['parameters']['TYPE']):arra
- +
- +
- +
- +
- +
- +
- +
diff --git a/apps/contacts/templates/settings.php b/apps/contacts/templates/settings.php index d77c4d3802..5627a15c50 100644 --- a/apps/contacts/templates/settings.php +++ b/apps/contacts/templates/settings.php @@ -8,6 +8,6 @@
t('iOS/OS X'); ?>
/principals//
+ Powered by geonames.org webservice - Powered by geonames.org webservice diff --git a/core/js/oc-vcategories.js b/core/js/oc-vcategories.js index a6dcccf88e..931ea37edb 100644 --- a/core/js/oc-vcategories.js +++ b/core/js/oc-vcategories.js @@ -19,7 +19,7 @@ OCCategories={ height: 350, minHeight:200, width: 250, minWidth: 200, buttons: { 'Delete':function() { - OCCategories.delete(); + OCCategories.do_delete(); }, 'Rescan':function() { OCCategories.rescan(); @@ -53,7 +53,7 @@ OCCategories={ } }); }, - delete:function(){ + do_delete:function(){ var categories = $('#categorylist').find('input[type="checkbox"]').serialize(); categories += '&app=' + OCCategories.app; console.log('OCCategories.delete: ' + categories);