From e248412ca9e9b75db5c7a4cc9651391e341c66f5 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Mon, 9 Jul 2012 16:07:26 +0200 Subject: [PATCH 01/31] use getStorage() to get versions location update routine implemented version number of files_versions increased Conflicts: apps/files_versions/lib/hooks.php --- apps/files_versions/ajax/expireAll.php | 2 +- apps/files_versions/appinfo/update.php | 16 ++ apps/files_versions/appinfo/version | 2 +- apps/files_versions/history.php | 2 +- apps/files_versions/lib/hooks.php | 69 ++++---- apps/files_versions/lib/versions.php | 226 +++++++++++-------------- 6 files changed, 158 insertions(+), 159 deletions(-) create mode 100644 apps/files_versions/appinfo/update.php diff --git a/apps/files_versions/ajax/expireAll.php b/apps/files_versions/ajax/expireAll.php index 238e3bdad4..4f165be0ae 100644 --- a/apps/files_versions/ajax/expireAll.php +++ b/apps/files_versions/ajax/expireAll.php @@ -28,7 +28,7 @@ OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('files_versions'); -$versions = new OCA_Versions\Storage( new OC_FilesystemView('') ); +$versions = new OCA_Versions\Storage(); if( $versions->expireAll() ){ diff --git a/apps/files_versions/appinfo/update.php b/apps/files_versions/appinfo/update.php new file mode 100644 index 0000000000..9569ca1048 --- /dev/null +++ b/apps/files_versions/appinfo/update.php @@ -0,0 +1,16 @@ +assign( 'path', $path ); - $versions = new OCA_Versions\Storage( new OC_FilesystemView('') ); + $versions = new OCA_Versions\Storage(); // roll back to old version if button clicked if( isset( $_GET['revert'] ) ) { diff --git a/apps/files_versions/lib/hooks.php b/apps/files_versions/lib/hooks.php index f93d4dabe2..bfc8fd3a37 100644 --- a/apps/files_versions/lib/hooks.php +++ b/apps/files_versions/lib/hooks.php @@ -30,41 +30,46 @@ class Hooks { } } - /** - * @brief Erase versions of deleted file - * @param array - * - * This function is connected to the delete signal of OC_Filesystem - * cleanup the versions directory if the actual file gets deleted - */ + + /** + * @brief Erase versions of deleted file + * @param array + * + * This function is connected to the delete signal of OC_Filesystem + * cleanup the versions directory if the actual file gets deleted + */ public static function remove_hook($params) { - $rel_path = $params['path']; - $abs_path = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_path.'.v'; - if(Storage::isversioned($rel_path)) { - $versions = Storage::getVersions($rel_path); - foreach ($versions as $v){ - unlink($abs_path . $v['version']); - } - } - } - - /** - * @brief rename/move versions of renamed/moved files - * @param array with oldpath and newpath - * - * This function is connected to the rename signal of OC_Filesystem and adjust the name and location - * of the stored versions along the actual file - */ + $versions_fileview = \OCP\Files::getStorage('files_versions'); + $rel_path = $params['path']; + $abs_path = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_path.'.v'; + if(Storage::isversioned($rel_path)) { + $versions = Storage::getVersions($rel_path); + foreach ($versions as $v){ + unlink($abs_path . $v['version']); + } + } + } + + /** + * @brief rename/move versions of renamed/moved files + * @param array with oldpath and newpath + * + * This function is connected to the rename signal of OC_Filesystem and adjust the name and location + * of the stored versions along the actual file + */ public static function rename_hook($params) { - $rel_oldpath = $params['oldpath']; - $abs_oldpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$rel_oldpath.'.v'; - $abs_newpath = \OCP\Config::getSystemValue('datadirectory').'/'.\OCP\User::getUser()."/versions".$params['newpath'].'.v'; + $versions_fileview = \OCP\Files::getStorage('files_versions'); + $rel_oldpath = $params['oldpath']; + $abs_oldpath = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$rel_oldpath.'.v'; + $abs_newpath = \OCP\Config::getSystemValue('datadirectory').$versions_fileview->getAbsolutePath('').$params['newpath'].'.v'; if(Storage::isversioned($rel_oldpath)) { - $versions = Storage::getVersions($rel_oldpath); - foreach ($versions as $v){ - rename($abs_oldpath.$v['version'], $abs_newpath.$v['version']); - } - } + $info=pathinfo($abs_newpath); + if(!file_exists($info['dirname'])) mkdir($info['dirname'],0700,true); + $versions = Storage::getVersions($rel_oldpath); + foreach ($versions as $v){ + rename($abs_oldpath.$v['version'], $abs_newpath.$v['version']); + } + } } } diff --git a/apps/files_versions/lib/versions.php b/apps/files_versions/lib/versions.php index 723c27577a..0ce884c3ea 100644 --- a/apps/files_versions/lib/versions.php +++ b/apps/files_versions/lib/versions.php @@ -22,41 +22,26 @@ class Storage { // - files_versionsfolder // - files_versionsblacklist // - files_versionsmaxfilesize - // - files_versionsinterval - // - files_versionmaxversions + // - files_versionsinterval + // - files_versionmaxversions // // todo: // - finish porting to OC_FilesystemView to enable network transparency // - add transparent compression. first test if it´s worth it. - const DEFAULTENABLED=true; - const DEFAULTFOLDER='versions'; - const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp'; - const DEFAULTMAXFILESIZE=1048576; // 10MB + const DEFAULTENABLED=true; + const DEFAULTBLACKLIST='avi mp3 mpg mp4 ctmp'; + const DEFAULTMAXFILESIZE=1048576; // 10MB const DEFAULTMININTERVAL=60; // 1 min const DEFAULTMAXVERSIONS=50; - + private $view; - - function __construct( $view ) { - - $this->view = $view; - - } - /** - * init the versioning and create the versions folder. - */ - public static function init() { - if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { - // create versions folder - $foldername=\OCP\Config::getSystemValue('datadirectory').'/'. \OCP\USER::getUser() .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); - if(!is_dir($foldername)){ - mkdir($foldername); - } - } - } + function __construct() { + $this->view = \OCP\Files::getStorage('files_versions'); + + } /** * listen to write event. @@ -75,11 +60,11 @@ class Storage { */ public function store($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { - + $files_view = \OCP\Files::getStorage("files"); $users_view = \OCP\Files::getStorage("files_versions"); $users_view->chroot(\OCP\User::getUser().'/'); - + if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) { $pos = strpos($source, '/files', 1); $uid = substr($source, 1, $pos - 1); @@ -87,15 +72,14 @@ class Storage { } else { $uid = \OCP\User::getUser(); } - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); - $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files'; - Storage::init(); - + + $versionsFolderName=\OCP\Config::getSystemValue('datadirectory') . $this->view->getAbsolutePath(''); + //check if source file already exist as version to avoid recursions. if ($users_view->file_exists($filename)) { return false; } - + // check if filename is a directory if($files_view->is_dir($filename)){ return false; @@ -110,7 +94,7 @@ class Storage { return false; } } - + // check filesize if($files_view->filesize($filename)>\OCP\Config::getSystemValue('files_versionsmaxfilesize', Storage::DEFAULTMAXFILESIZE)){ return false; @@ -129,12 +113,12 @@ class Storage { // create all parent folders - $info=pathinfo($filename); - if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true); + $info=pathinfo($filename); + if(!file_exists($versionsFolderName.'/'.$info['dirname'])) mkdir($versionsFolderName.'/'.$info['dirname'],0700,true); // store a new version of a file - @$users_view->copy('files'.$filename, 'versions'.$filename.'.v'.time()); - + @$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.time()); + // expire old revisions if necessary Storage::expire($filename); } @@ -145,11 +129,11 @@ class Storage { * rollback to an old version of a file. */ public static function rollback($filename,$revision) { - + if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { $users_view = \OCP\Files::getStorage("files_versions"); $users_view->chroot(\OCP\User::getUser().'/'); - + if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) { $pos = strpos($source, '/files', 1); $uid = substr($source, 1, $pos - 1); @@ -157,23 +141,20 @@ class Storage { } else { $uid = \OCP\User::getUser(); } - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'.$uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); - - $filesfoldername=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/files'; - + // rollback - if( @$users_view->copy('versions'.$filename.'.v'.$revision, 'files'.$filename) ) { - + if( @$users_view->copy('files_versions'.$filename.'.v'.$revision, 'files'.$filename) ) { + return true; - + }else{ - + return false; - + } - + } - + } /** @@ -181,18 +162,17 @@ class Storage { */ public static function isversioned($filename) { if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { + $versions_fileview = \OCP\Files::getStorage("files_versions"); if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) { $pos = strpos($source, '/files', 1); - $uid = substr($source, 1, $pos - 1); $filename = substr($source, $pos + 6); - } else { - $uid = \OCP\User::getUser(); } - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); + $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); + // check for old versions - $matches=glob($versionsFolderName.'/'.$filename.'.v*'); - if(count($matches)>1){ + $matches=glob($versionsFolderName.$filename.'.v*'); + if(count($matches)>0){ return true; }else{ return false; @@ -203,17 +183,17 @@ class Storage { } - - /** - * @brief get a list of all available versions of a file in descending chronological order - * @param $filename file to find versions of, relative to the user files dir - * @param $count number of versions to return - * @returns array - */ - public static function getVersions( $filename, $count = 0 ) { - - if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { - + + /** + * @brief get a list of all available versions of a file in descending chronological order + * @param $filename file to find versions of, relative to the user files dir + * @param $count number of versions to return + * @returns array + */ + public static function getVersions( $filename, $count = 0 ) { + + if( \OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true' ) { + if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) { $pos = strpos($source, '/files', 1); $uid = substr($source, 1, $pos - 1); @@ -221,70 +201,71 @@ class Storage { } else { $uid = \OCP\User::getUser(); } - $versionsFolderName = \OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); - $versions = array(); - + $versions_fileview = \OCP\Files::getStorage('files_versions'); + $versionsFolderName = \OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); + $versions = array(); + // fetch for old versions $matches = glob( $versionsFolderName.'/'.$filename.'.v*' ); - - sort( $matches ); - - $i = 0; - - foreach( $matches as $ma ) { + sort( $matches ); + + $i = 0; + + $files_view = \OCP\Files::getStorage('files'); + $local_file = $files_view->getLocalFile($filename); + foreach( $matches as $ma ) { + $i++; $versions[$i]['cur'] = 0; $parts = explode( '.v', $ma ); $versions[$i]['version'] = ( end( $parts ) ); - + // if file with modified date exists, flag it in array as currently enabled version - $files_view = \OCP\Files::getStorage('files'); - $local_file = $files_view->getLocalFile($filename); ( \md5_file( $ma ) == \md5_file( $local_file ) ? $versions[$i]['fileMatch'] = 1 : $versions[$i]['fileMatch'] = 0 ); - + } - - $versions = array_reverse( $versions ); - - foreach( $versions as $key => $value ) { + $versions = array_reverse( $versions ); + + foreach( $versions as $key => $value ) { + // flag the first matched file in array (which will have latest modification date) as current version if ( $versions[$key]['fileMatch'] ) { - + $versions[$key]['cur'] = 1; break; - + } - + } - + $versions = array_reverse( $versions ); - + // only show the newest commits if( $count != 0 and ( count( $versions )>$count ) ) { - + $versions = array_slice( $versions, count( $versions ) - $count ); - + } - + return( $versions ); - } else { - - // if versioning isn't enabled then return an empty array - return( array() ); - - } - - } + } else { - /** - * @brief Erase a file's versions which exceed the set quota - */ - public static function expire($filename) { - if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { + // if versioning isn't enabled then return an empty array + return( array() ); + + } + + } + + /** + * @brief Erase a file's versions which exceed the set quota + */ + public static function expire($filename) { + if(\OCP\Config::getSystemValue('files_versions', Storage::DEFAULTENABLED)=='true') { if (\OCP\App::isEnabled('files_sharing') && $source = \OC_Share::getSource('/'.\OCP\User::getUser().'/files'.$filename)) { $pos = strpos($source, '/files', 1); @@ -293,36 +274,33 @@ class Storage { } else { $uid = \OCP\User::getUser(); } - $versionsFolderName=\OCP\Config::getSystemValue('datadirectory').'/'. $uid .'/'.\OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); + $versions_fileview = \OCP\Files::getStorage("files_versions"); + $versionsFolderName=\OCP\Config::getSystemValue('datadirectory'). $versions_fileview->getAbsolutePath(''); // check for old versions $matches = glob( $versionsFolderName.'/'.$filename.'.v*' ); - + if( count( $matches ) > \OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ) { - + $numberToDelete = count( $matches-\OCP\Config::getSystemValue( 'files_versionmaxversions', Storage::DEFAULTMAXVERSIONS ) ); // delete old versions of a file $deleteItems = array_slice( $matches, 0, $numberToDelete ); - + foreach( $deleteItems as $de ) { - + unlink( $versionsFolderName.'/'.$filename.'.v'.$de ); - + } } - } - } + } + } - /** - * @brief Erase all old versions of all user files - * @return true/false - */ - public function expireAll() { - - $dir = \OCP\Config::getSystemValue('files_versionsfolder', Storage::DEFAULTFOLDER); - - return $this->view->deleteAll( $dir, true ); - - } + /** + * @brief Erase all old versions of all user files + * @return true/false + */ + public function expireAll() { + return $this->view->deleteAll('', true); + } } From 07efd39d8a1b82f61f5ed429cd713c04c5988788 Mon Sep 17 00:00:00 2001 From: Bjoern Schiessle Date: Wed, 11 Jul 2012 15:44:39 +0200 Subject: [PATCH 02/31] prevent script execution during slideshow --- apps/gallery/js/slideshow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gallery/js/slideshow.js b/apps/gallery/js/slideshow.js index 88e89f39ff..cc5dfc44a2 100644 --- a/apps/gallery/js/slideshow.js +++ b/apps/gallery/js/slideshow.js @@ -15,7 +15,7 @@ $(document).ready(function(){ var images=[]; $('#gallerycontent div a').each(function(i,a){ - images.push({image : a.href, title : a.title, thumb : a.children[0].src, url : 'javascript:$.endSlideshow()'}); + images.push({image : a.href, title : a.title.replace(//, '>'), thumb : a.children[0].src, url : 'javascript:$.endSlideshow()'}); }); if (images.length <= 0) { From c3fea30811f845fe357b70d5beb511ca4ad42eca Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Wed, 11 Jul 2012 19:14:04 +0200 Subject: [PATCH 03/31] Sanitizing file names --- apps/files/js/filelist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index e6a9a6883a..3645258f98 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -14,7 +14,7 @@ FileList={ var extension=false; } html+=''; - html+=''+basename + html+=''+basename if(extension){ html+=''+extension+''; } From 7077678f7fb33b376e05eece3b62dc4ae058055a Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 11 Jul 2012 15:26:22 -0400 Subject: [PATCH 04/31] Sanitize toaddress for emailing private links --- apps/files_sharing/ajax/email.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/ajax/email.php b/apps/files_sharing/ajax/email.php index ca63f540f9..0765bdd988 100644 --- a/apps/files_sharing/ajax/email.php +++ b/apps/files_sharing/ajax/email.php @@ -5,9 +5,10 @@ OCP\JSON::callCheck(); $user = OCP\USER::getUser(); // TODO translations +$toaddress = OCP\Util::sanitizeHtml($_POST['toaddress']); $type = (strpos($_POST['file'], '.') === false) ? 'folder' : 'file'; $subject = $user.' shared a '.$type.' with you'; $link = $_POST['link']; $text = $user.' shared the '.$type.' '.$_POST['file'].' with you. It is available for download here: '.$link; $fromaddress = OCP\Config::getUserValue($user, 'settings', 'email', 'sharing-noreply@'.OCP\Util::getServerHost()); -OC_Mail::send($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user); +OCP\Util::sendMail($toaddress, $toaddress, $subject, $text, $fromaddress, $user); From 66da0a215137ef03b31a6b5706007e503aa1ad0a Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 11 Jul 2012 15:36:27 -0400 Subject: [PATCH 05/31] Catch exceptions from PHPMailer --- lib/mail.php | 54 +++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/lib/mail.php b/lib/mail.php index 7343f5f0d9..9d2cd62494 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -56,33 +56,35 @@ class OC_Mail { $mailo->From =$fromaddress; $mailo->FromName = $fromname;; $a=explode(' ',$toaddress); - foreach($a as $ad) { - $mailo->AddAddress($ad,$toname); + try { + foreach($a as $ad) { + $mailo->AddAddress($ad,$toname); + } + + if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname); + if($bcc<>'') $mailo->AddBCC($bcc); + + $mailo->AddReplyTo($fromaddress, $fromname); + + $mailo->WordWrap = 50; + if($html==1) $mailo->IsHTML(true); else $mailo->IsHTML(false); + + $mailo->Subject = $subject; + if($altbody=='') { + $mailo->Body = $mailtext.OC_MAIL::getfooter(); + $mailo->AltBody = ''; + }else{ + $mailo->Body = $mailtext; + $mailo->AltBody = $altbody; + } + $mailo->CharSet = 'UTF-8'; + + $mailo->Send(); + unset($mailo); + OC_Log::write('Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject,'mail',OC_Log::DEBUG); + } catch (Exception $exception) { + OC_Log::write('mail', $exception->getMessage(), OC_Log::DEBUG); } - - if($ccaddress<>'') $mailo->AddCC($ccaddress,$ccname); - if($bcc<>'') $mailo->AddBCC($bcc); - - $mailo->AddReplyTo($fromaddress, $fromname); - - $mailo->WordWrap = 50; - if($html==1) $mailo->IsHTML(true); else $mailo->IsHTML(false); - - $mailo->Subject = $subject; - if($altbody=='') { - $mailo->Body = $mailtext.OC_MAIL::getfooter(); - $mailo->AltBody = ''; - }else{ - $mailo->Body = $mailtext; - $mailo->AltBody = $altbody; - } - $mailo->CharSet = 'UTF-8'; - - $mailo->Send(); - unset($mailo); - - OC_Log::write('Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject,'mail',OC_Log::DEBUG); - } From 8afcddf44fedc706108dc318c146a777ca2a4988 Mon Sep 17 00:00:00 2001 From: Lukas Reschke Date: Wed, 11 Jul 2012 21:52:51 +0200 Subject: [PATCH 06/31] Handling exceptions --- lib/mail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mail.php b/lib/mail.php index 9d2cd62494..545b95da87 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -36,7 +36,7 @@ class OC_Mail { $SMTPPASSWORD = OC_Config::getValue( 'mail_smtppassword', '' ); - $mailo = new PHPMailer(); + $mailo = new PHPMailer(true); if($SMTPMODE=='sendmail') { $mailo->IsSendmail(); }elseif($SMTPMODE=='smtp'){ From 281bf62af93e373d761b767af6cc316e4681d66a Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 11 Jul 2012 15:41:59 -0400 Subject: [PATCH 07/31] Fix log write() parameters in wrong order --- lib/mail.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mail.php b/lib/mail.php index 545b95da87..7eb2c4770c 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -81,7 +81,7 @@ class OC_Mail { $mailo->Send(); unset($mailo); - OC_Log::write('Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject,'mail',OC_Log::DEBUG); + OC_Log::write('mail', 'Mail from '.$fromname.' ('.$fromaddress.')'.' to: '.$toname.'('.$toaddress.')'.' subject: '.$subject, OC_Log::DEBUG); } catch (Exception $exception) { OC_Log::write('mail', $exception->getMessage(), OC_Log::DEBUG); } From 91a15bae76c4c4fca456c38fb51c8b944c92c341 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 11 Jul 2012 16:02:43 -0400 Subject: [PATCH 08/31] Revert santizing toaddress, because PHPMailer now throws exceptions --- apps/files_sharing/ajax/email.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/files_sharing/ajax/email.php b/apps/files_sharing/ajax/email.php index 0765bdd988..3026eb7467 100644 --- a/apps/files_sharing/ajax/email.php +++ b/apps/files_sharing/ajax/email.php @@ -5,10 +5,9 @@ OCP\JSON::callCheck(); $user = OCP\USER::getUser(); // TODO translations -$toaddress = OCP\Util::sanitizeHtml($_POST['toaddress']); $type = (strpos($_POST['file'], '.') === false) ? 'folder' : 'file'; $subject = $user.' shared a '.$type.' with you'; $link = $_POST['link']; $text = $user.' shared the '.$type.' '.$_POST['file'].' with you. It is available for download here: '.$link; $fromaddress = OCP\Config::getUserValue($user, 'settings', 'email', 'sharing-noreply@'.OCP\Util::getServerHost()); -OCP\Util::sendMail($toaddress, $toaddress, $subject, $text, $fromaddress, $user); +OCP\Util::sendMail($_POST['toaddress'], $_POST['toaddress'], $subject, $text, $fromaddress, $user); From 8890a4128015df0ad57101703d6c164ea54fe4ee Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Thu, 28 Jun 2012 21:26:39 -0400 Subject: [PATCH 09/31] Fix setting custom quota size for users, bug fix for oc-1128 --- settings/js/users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings/js/users.js b/settings/js/users.js index dfa28e4c4c..771ed51f5f 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -186,7 +186,7 @@ $(document).ready(function(){ }) $('input.quota-other').live('change',function(){ - var uid=$(this).parent().parent().data('uid'); + var uid=$(this).parent().parent().parent().data('uid'); var quota=$(this).val(); var select=$(this).prev(); var other=$(this); From f496a9dea69ec387eb6979916c2569dc4d81b47e Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Wed, 11 Jul 2012 20:28:29 -0400 Subject: [PATCH 10/31] Rename $contacts to $has_contacts, it missed this commit: 7cb74a0 --- apps/contacts/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contacts/index.php b/apps/contacts/index.php index c1e33252f5..fbc3565c4d 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -15,7 +15,7 @@ OCP\App::checkAppEnabled('contacts'); // Get active address books. This creates a default one if none exists. $ids = OC_Contacts_Addressbook::activeIds(OCP\USER::getUser()); $has_contacts = (count(OC_Contacts_VCard::all($ids, 0, 1)) > 0 ? true : false); // just to check if there are any contacts. -if($contacts === false) { +if($has_contacts === false) { OCP\Util::writeLog('contacts','index.html: No contacts found.',OCP\Util::DEBUG); } From 967c6d7d3cfeb2f504ddc4301b902b39377c45fb Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Fri, 13 Jul 2012 13:25:43 +0200 Subject: [PATCH 11/31] allow command line based installation/setup --- lib/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/setup.php b/lib/setup.php index 2f73c486c9..027c84db09 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -257,7 +257,7 @@ class OC_Setup { OC_Installer::installShippedApps(); //create htaccess files for apache hosts - if (strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { + if (isset($_SERVER['SERVER_SOFTWARE']) && strstr($_SERVER['SERVER_SOFTWARE'], 'Apache')) { self::createHtaccess(); } From 5de2a292fcfe9174542e7708b033c8026a2c46a6 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Fri, 13 Jul 2012 13:41:13 +0200 Subject: [PATCH 12/31] restructuring test suite invocation - now we load all test cases into one suite and execute this single suite. this is necessary to be able to generate one xml report and is also a precondition for code coverage analysis(which will follow soon) --- tests/index.php | 52 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/tests/index.php b/tests/index.php index 691bf2a5d4..e91b3f0da5 100644 --- a/tests/index.php +++ b/tests/index.php @@ -26,39 +26,59 @@ require_once 'simpletest/mock_objects.php'; require_once 'simpletest/collector.php'; require_once 'simpletest/default_reporter.php'; +// test suite instance +$testSuite=new TestSuite("ownCloud Unit Test Suite"); + +// prepare the reporter +if(OC::$CLI){ + $reporter=new TextReporter; + $test=isset($_SERVER['argv'][1])?$_SERVER['argv'][1]:false; + if($test=='xml') + { + $reporter= new XmlReporter; + $test=false; + } +}else{ + $reporter='HtmlReporter'; + $test=isset($_GET['test'])?$_GET['test']:false; +} + //load core test cases -loadTests(dirname(__FILE__)); +loadTests(dirname(__FILE__), $testSuite, $test); //load app test cases + +// +// TODO: define a list of apps to be enabled + enable them +// + $apps=OC_App::getEnabledApps(); foreach($apps as $app){ if(is_dir(OC::$SERVERROOT.'/apps/'.$app.'/tests')){ - loadTests(OC::$SERVERROOT.'/apps/'.$app.'/tests'); + loadTests(OC::$SERVERROOT.'/apps/'.$app.'/tests', $testSuite, $test); } } -function loadTests($dir=''){ - if(OC::$CLI){ - $reporter='TextReporter'; - $test=isset($_SERVER['argv'][1])?$_SERVER['argv'][1]:false; - }else{ - $reporter='HtmlReporter'; - $test=isset($_GET['test'])?$_GET['test']:false; - } +// run the suite +if($testSuite->getSize()>0){ + $testSuite->run($reporter); +} + +// helper below +function loadTests($dir,$testSuite, $test){ if($dh=opendir($dir)){ while($name=readdir($dh)){ if($name[0]!='.'){//no hidden files, '.' or '..' $file=$dir.'/'.$name; if(is_dir($file)){ - loadTests($file); + loadTests($file, $testSuite, $test); }elseif(substr($file,-4)=='.php' and $file!=__FILE__){ $name=getTestName($file); if($test===false or $test==$name or substr($name,0,strlen($test))==$test){ - $testCase=new TestSuite($name); - $testCase->addFile($file); - if($testCase->getSize()>0){ - $testCase->run(new $reporter()); - } + $extractor = new SimpleFileLoader(); + $loadedSuite=$extractor->load($file); + if ($loadedSuite->getSize() > 0) + $testSuite->add($loadedSuite); } } } From fd0c6da41009b20b0c0906d8ec895cbab54af832 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Fri, 13 Jul 2012 13:55:15 +0200 Subject: [PATCH 13/31] autotest.sh added: create an fresh environment using sqlite (mysql anf pg will follow) and executes the test suite --- autotest.sh | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100755 autotest.sh diff --git a/autotest.sh b/autotest.sh new file mode 100755 index 0000000000..a5e28b6de9 --- /dev/null +++ b/autotest.sh @@ -0,0 +1,32 @@ +#preparation +echo "Setup environment for sqlite testing ..." +DATADIR=data-autotest +rm -rf $DATADIR +mkdir $DATADIR +rm -rf config/config.php +#cp autotest/config.sqlite.php config/autoconfig.php +cat > ./config/autoconfig.php < false, + 'dbtype' => 'sqlite', + 'dbtableprefix' => 'oc_', + 'datadirectory' => 'data', + 'adminlogin' => 'admin', + 'adminpass' => 'admin', + 'directory' => '$PWD/$DATADIR', +); +DELIM + +php -f index.php + +#test execution +echo 'Testing with sqlite ...' +cd tests +php -f index.php -- xml + + +# +# TODO: create config for mysql and postgres +# + From 6ee228cac7e5aca1181113ca499bda6c04497da7 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Fri, 13 Jul 2012 15:10:30 +0200 Subject: [PATCH 14/31] rediect test results to autotest-results-sqlite.xml --- autotest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autotest.sh b/autotest.sh index a5e28b6de9..a9794db698 100755 --- a/autotest.sh +++ b/autotest.sh @@ -23,7 +23,7 @@ php -f index.php #test execution echo 'Testing with sqlite ...' cd tests -php -f index.php -- xml +php -f index.php -- xml > autotest-results-sqlite.xml # From b45d3ced79b5a20034c85973760e2f120e1574e7 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 13 Jul 2012 22:44:35 +0200 Subject: [PATCH 15/31] fix remote and public.php --- apps/calendar/appinfo/version | 2 +- apps/contacts/appinfo/version | 2 +- apps/files/appinfo/version | 2 +- apps/files_sharing/appinfo/version | 2 +- apps/gallery/appinfo/version | 2 +- apps/media/appinfo/version | 2 +- lib/app.php | 2 +- public.php | 1 + remote.php | 10 ++++------ 9 files changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/calendar/appinfo/version b/apps/calendar/appinfo/version index 2eb3c4fe4e..cb0c939a93 100644 --- a/apps/calendar/appinfo/version +++ b/apps/calendar/appinfo/version @@ -1 +1 @@ -0.5 +0.5.2 diff --git a/apps/contacts/appinfo/version b/apps/contacts/appinfo/version index 7dff5b8921..373f8c6f07 100644 --- a/apps/contacts/appinfo/version +++ b/apps/contacts/appinfo/version @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.2.3 \ No newline at end of file diff --git a/apps/files/appinfo/version b/apps/files/appinfo/version index 8cfbc905b3..9c1218c201 100644 --- a/apps/files/appinfo/version +++ b/apps/files/appinfo/version @@ -1 +1 @@ -1.1.1 \ No newline at end of file +1.1.3 \ No newline at end of file diff --git a/apps/files_sharing/appinfo/version b/apps/files_sharing/appinfo/version index 7dff5b8921..f4778493c5 100644 --- a/apps/files_sharing/appinfo/version +++ b/apps/files_sharing/appinfo/version @@ -1 +1 @@ -0.2.1 \ No newline at end of file +0.2.2 \ No newline at end of file diff --git a/apps/gallery/appinfo/version b/apps/gallery/appinfo/version index 8f0916f768..4b9fcbec10 100644 --- a/apps/gallery/appinfo/version +++ b/apps/gallery/appinfo/version @@ -1 +1 @@ -0.5.0 +0.5.1 diff --git a/apps/media/appinfo/version b/apps/media/appinfo/version index e6adf3fc7b..44bb5d1f74 100644 --- a/apps/media/appinfo/version +++ b/apps/media/appinfo/version @@ -1 +1 @@ -0.4 \ No newline at end of file +0.4.1 \ No newline at end of file diff --git a/lib/app.php b/lib/app.php index 4c2c43ec26..caf8bd8252 100755 --- a/lib/app.php +++ b/lib/app.php @@ -608,7 +608,7 @@ class OC_App{ //set remote/public handelers $appData=self::getAppInfo($appid); foreach($appData['remote'] as $name=>$path){ - OCP\CONFIG::setAppValue('core', 'remote_'.$name, $path); + OCP\CONFIG::setAppValue('core', 'remote_'.$name, $appid.'/'.$path); } foreach($appData['public'] as $name=>$path){ OCP\CONFIG::setAppValue('core', 'public_'.$name, $appid.'/'.$path); diff --git a/public.php b/public.php index 8846769f46..8383f36a24 100644 --- a/public.php +++ b/public.php @@ -10,6 +10,7 @@ if(is_null($file)){ $parts=explode('/',$file,2); $app=$parts[0]; + OC_Util::checkAppEnabled($app); OC_App::loadApp($app); diff --git a/remote.php b/remote.php index bdce867aab..8c02c24e2a 100644 --- a/remote.php +++ b/remote.php @@ -15,27 +15,25 @@ if (!$pos = strpos($path_info, '/', 1)) { $pos = strlen($path_info); } $service=substr($path_info, 1, $pos-1); + $file = OC_AppConfig::getValue('core', 'remote_' . $service); -$file = preg_replace('/apps\//','', $file); //Todo Remove after Multiappdir migration if(is_null($file)){ OC_Response::setStatus(OC_Response::STATUS_NOT_FOUND); exit; } -$file = ltrim ($file, '/'); - $parts=explode('/', $file, 2); $app=$parts[0]; switch ($app) { + case 'core': + $file = OC::$SERVERROOT .'/'. $file; + break; default: OC_Util::checkAppEnabled($app); OC_App::loadApp($app); $file = OC_App::getAppPath($app) .'/'. $parts[1]; break; - case 'core': - $file = OC::$SERVERROOT .'/'. $file; - break; } $baseuri = OC::$WEBROOT . '/remote.php/'.$service.'/'; require_once($file); From 7d1f644011e23d19cc22d431ae5e6cf31144db50 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 13 Jul 2012 23:24:22 +0200 Subject: [PATCH 16/31] use new way to register remote/public.php entries in user_webfinger --- apps/user_webfinger/appinfo/app.php | 2 -- apps/user_webfinger/appinfo/info.xml | 4 ++++ apps/user_webfinger/appinfo/version | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/user_webfinger/appinfo/app.php b/apps/user_webfinger/appinfo/app.php index 3336af6682..b3d9bbc7f3 100644 --- a/apps/user_webfinger/appinfo/app.php +++ b/apps/user_webfinger/appinfo/app.php @@ -1,3 +1 @@ Michiel de Jong, Florian Hülsmann 4 true + + host-meta.php + webfinger.php + diff --git a/apps/user_webfinger/appinfo/version b/apps/user_webfinger/appinfo/version index 1d71ef9744..a2268e2de4 100644 --- a/apps/user_webfinger/appinfo/version +++ b/apps/user_webfinger/appinfo/version @@ -1 +1 @@ -0.3 \ No newline at end of file +0.3.1 \ No newline at end of file From 880d80be674fe4cc5c6be40980567ccd4b4553a5 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sat, 14 Jul 2012 00:10:17 +0200 Subject: [PATCH 17/31] fix minified js and css --- remote.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/remote.php b/remote.php index 8c02c24e2a..8461eea19a 100644 --- a/remote.php +++ b/remote.php @@ -23,6 +23,8 @@ if(is_null($file)){ exit; } +$file=ltrim($file,'/'); + $parts=explode('/', $file, 2); $app=$parts[0]; switch ($app) { From d45d73eecfcc4cff7e7edba8678509e78bec7e07 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 10 Jul 2012 13:16:26 +0200 Subject: [PATCH 18/31] Try to avoid occasional error messages. --- apps/contacts/js/jquery.inview.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/contacts/js/jquery.inview.js b/apps/contacts/js/jquery.inview.js index 01900b0b4b..9687cd8336 100644 --- a/apps/contacts/js/jquery.inview.js +++ b/apps/contacts/js/jquery.inview.js @@ -62,8 +62,8 @@ function getViewportOffset() { return { - top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop, - left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft + top: w.pageYOffset || documentElement.scrollTop || (d.body?d.body.scrollTop:0), + left: w.pageXOffset || documentElement.scrollLeft || (d.body?d.body.scrollLeft:0) }; } From 140263003afd35360a734fab7b32ca7b0dcbb3a0 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Tue, 10 Jul 2012 14:55:03 +0200 Subject: [PATCH 19/31] Give default address book a more intuitive name and replace spaces with underscores in uri. --- apps/contacts/lib/addressbook.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/contacts/lib/addressbook.php b/apps/contacts/lib/addressbook.php index a31ee25461..9d584ff6d6 100644 --- a/apps/contacts/lib/addressbook.php +++ b/apps/contacts/lib/addressbook.php @@ -133,7 +133,7 @@ class OC_Contacts_Addressbook{ if(is_null($uid)) { $uid = OCP\USER::getUser(); } - $id = self::add($uid,'default','Default Address Book'); + $id = self::add($uid,'Contacts','Default Address Book'); if($id !== false) { self::setActive($id, true); } @@ -306,7 +306,7 @@ class OC_Contacts_Addressbook{ * @return string new name */ public static function createURI($name,$existing){ - $name = strtolower($name); + $name = str_replace(' ', '_', strtolower($name)); $newname = $name; $i = 1; while(in_array($newname,$existing)){ From b455149bae9d764e36f2f61bfdea58f7c8d1f040 Mon Sep 17 00:00:00 2001 From: Michael Gapczynski Date: Sat, 14 Jul 2012 16:56:17 -0400 Subject: [PATCH 20/31] Fix undo delete user --- settings/js/users.js | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/settings/js/users.js b/settings/js/users.js index 771ed51f5f..63ad426ecf 100644 --- a/settings/js/users.js +++ b/settings/js/users.js @@ -47,25 +47,24 @@ UserList={ if( !UserList.deleteCanceled && UserList.deleteUid ){ // Delete user via ajax - $.post( - OC.filePath('settings','ajax','removeuser.php'), - {username:UserList.deleteUid}, - function(result){ - - // Remove undo option, & remove user from table - boolOperationFinished( - data, function(){ - $('#notification').fadeOut(); - $('tr').filterAttr( 'data-uid', username ).remove(); - UserList.deleteCanceled=true; - UserList.deleteFiles=null; - if( ready ){ - ready(); - } + $.ajax({ + type: 'POST', + url: OC.filePath('settings', 'ajax', 'removeuser.php'), + async: false, + data: { username: UserList.deleteUid }, + success: function(result) { + if (result.status == 'success') { + // Remove undo option, & remove user from table + $('#notification').fadeOut(); + $('tr').filterAttr('data-uid', UserList.deleteUid).remove(); + UserList.deleteCanceled = true; + UserList.deleteFiles = null; + if (ready) { + ready(); } - ); + } } - ); + }); } } } From 87912a8c6595e90b3248bc84dce6e0693253b81d Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sat, 14 Jul 2012 14:25:25 +0200 Subject: [PATCH 21/31] Fix loading previous or next contact after deleting one. --- apps/contacts/js/contacts.js | 203 ++++++++++++++++++++++++++++++----- 1 file changed, 177 insertions(+), 26 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index dd194db016..b0274201ac 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -258,7 +258,7 @@ Contacts={ $('#contacts_deletecard').tipsy({gravity: 'ne'}); $('#contacts_downloadcard').tipsy({gravity: 'ne'}); $('#contacts_propertymenu_button').tipsy(); - $('#contacts_newcontact, #chooseaddressbook').tipsy({gravity: 'sw'}); + $('#contacts_newcontact, #contacts_import, #chooseaddressbook').tipsy({gravity: 'sw'}); $('body').click(function(e){ if(!$(e.target).is('#contacts_propertymenu_button')) { @@ -441,13 +441,13 @@ Contacts={ var newid = '', bookid; var curlistitem = $('#contacts li[data-id="'+jsondata.data.id+'"]'); var newlistitem = curlistitem.prev('li'); - if(newlistitem == undefined) { + if(!newlistitem) { newlistitem = curlistitem.next('li'); } curlistitem.remove(); - if(!$(newlistitem).is('li')) { + if($(newlistitem).is('li')) { newid = newlistitem.data('id'); - bookid = newlistitem.data('id'); + bookid = newlistitem.data('bookid'); } $('#rightcontent').data('id',newid); this.id = this.fn = this.fullname = this.shortname = this.famname = this.givname = this.addname = this.honpre = this.honsuf = ''; @@ -774,6 +774,7 @@ Contacts={ } }, deleteProperty:function(obj, type){ + console.log('deleteProperty'); Contacts.UI.loading(obj, true); var checksum = Contacts.UI.checksumFor(obj); if(checksum) { @@ -1377,6 +1378,21 @@ Contacts={ } }); }, + addAddressbook:function(name, description, cb) { + $.post(OC.filePath('contacts', 'ajax', 'addaddressbook.php'), { name: name, description: description, active: true }, + function(jsondata){ + if(jsondata.status == 'success'){ + if(cb) { + cb(jsondata.data); + } + //Contacts.UI.Contacts.update(); + } else { + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + return false; + } + }); + + }, newAddressbook:function(object){ var tr = $(document.createElement('tr')) .load(OC.filePath('contacts', 'ajax', 'addbook.php')); @@ -1508,25 +1524,24 @@ Contacts={ .load(OC.filePath('contacts', 'ajax', 'importaddressbook.php')); $(object).closest('tr').after(tr).hide(); }, - doImport:function(path, file){ - $(Contacts.UI.Addressbooks.droptarget).html(t('contacts', 'Importing...')); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); - var id = $('#importaddressbook_dialog').find('#book').val(); - $.post(OC.filePath('contacts', '', 'import.php'), { id: id, path: path, file: file, fstype: 'OC_FilesystemView' }, - function(jsondata){ - if(jsondata.status == 'success'){ - Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Import done. Success/Failure: ')+jsondata.data.imported+'/'+jsondata.data.failed); - $('#chooseaddressbook_dialog').find('#close_button').val(t('contacts', 'OK')); - Contacts.UI.Contacts.update(); - setTimeout( - function() { - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - }, 5000); - } else { - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); + doImport:function(name, file, aid){ + var cImport = function(id, file) { + $.post(OC.filePath('contacts', '', 'import.php'), { id: id, file: file, fstype: 'OC_FilesystemView' }, + function(jsondata){ + if(jsondata.status == 'success'){ + Contacts.UI.Contacts.update(undefined, id); + } else { + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + } + if(!aid) { + aid = Contacts.UI.Addressbooks.addAddressbook(name, t('contacts', 'Imported address book'), function(addressbook) { + cImport(addressbook.id, file); + }); + } else { + cImport(aid, file); + } }, submit:function(button, bookid){ var displayname = $("#displayname_"+bookid).val().trim(); @@ -1591,6 +1606,13 @@ Contacts={ }, // Reload the contacts list. update:function(id, aid, start){ + if(!start) { + if(aid) { + $('#contacts h3[data-id="'+aid+'"],#contacts ul[data-id="'+aid+'"]').remove(); + } else { + $('#contacts').empty(); + } + } self = this; console.log('update: ' + aid + ' ' + start); var firstrun = false; @@ -1605,12 +1627,12 @@ Contacts={ $.each(jsondata.data.entries, function(b, book) { if($('#contacts h3[data-id="'+b+'"]').length == 0) { firstrun = true; - + // TODO: Make sure address books are sorted properly. if($('#contacts h3').length == 0) { - $('#contacts').html('

'+book.displayname+'

'); + $('#contacts').html('

'+book.displayname+'

'); } else { if(!$('#contacts h3[data-id="'+b+'"]').length) { - $('

'+book.displayname+'

') + $('

'+book.displayname+'

') .appendTo('#contacts'); } } @@ -1800,6 +1822,135 @@ $(document).ready(function(){ xhr.send(file); } + // Import using jquery.fileupload + $(function() { + $('#contacts_import').click(function() { + $('#import_upload_start').click(); + return false; + }); + $('#import_upload_start').fileupload({ + dropZone: $('#contacts'), // restrict dropZone to content div + add: function(e, data) { + var files = data.files; + var totalSize=0; + if(files){ + for(var i=0;i$('#max_upload').val()){ + console.log('upload too large'); + }else{ + if($.support.xhrFileUpload) { + // TODO: First upload file(s) and cache names in an array, then check if we know + // the aid, otherwise ask user, then import files. + for(var i=0;i tr').not('[data-mime]').fadeOut(); + $('#fileList > tr').not('[data-mime]').remove(); + } + }); + } + } + }, + fail: function(e, data) { + console.log('fail'); + // TODO: cancel upload & display error notification + }, + progress: function(e, data) { + // TODO: show nice progress bar in file row + }, + progressall: function(e, data) { + var progress = (data.loaded/data.total)*100; + console.log('progress: ' + progress); + $('#uploadprogressbar').progressbar('value',progress); + }, + start: function(e, data) { + console.log('start'); + $('#uploadprogressbar').progressbar({value:0}); + $('#uploadprogressbar').fadeIn(); + if(data.dataType != 'iframe ') { + $('#upload input.stop').show(); + } + }, + stop: function(e, data) { + console.log('stop'); + if(data.dataType != 'iframe ') { + $('#upload input.stop').hide(); + } + $('#uploadprogressbar').progressbar('value',100); + $('#uploadprogressbar').fadeOut(); + } + }) + }); + Contacts.UI.loadHandlers(); Contacts.UI.Contacts.update(id); }); From eba4f080159f0a97f82c79f8b57b6ce45ef127b5 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 04:15:57 +0200 Subject: [PATCH 22/31] Refactored contacts import. --- apps/contacts/ajax/addaddressbook.php | 35 ++ apps/contacts/ajax/importaddressbook.php | 23 - apps/contacts/ajax/selectaddressbook.php | 16 + apps/contacts/ajax/uploadimport.php | 12 +- apps/contacts/css/contacts.css | 1 + apps/contacts/import.php | 7 +- apps/contacts/index.php | 1 + apps/contacts/js/contacts.js | 417 ++++++++---------- apps/contacts/lib/app.php | 2 +- apps/contacts/templates/index.php | 15 +- .../templates/part.chooseaddressbook.php | 1 - .../templates/part.importaddressbook.php | 38 -- .../templates/part.selectaddressbook.php | 27 ++ 13 files changed, 286 insertions(+), 309 deletions(-) create mode 100644 apps/contacts/ajax/addaddressbook.php delete mode 100644 apps/contacts/ajax/importaddressbook.php create mode 100644 apps/contacts/ajax/selectaddressbook.php delete mode 100644 apps/contacts/templates/part.importaddressbook.php create mode 100644 apps/contacts/templates/part.selectaddressbook.php diff --git a/apps/contacts/ajax/addaddressbook.php b/apps/contacts/ajax/addaddressbook.php new file mode 100644 index 0000000000..3d7885fe46 --- /dev/null +++ b/apps/contacts/ajax/addaddressbook.php @@ -0,0 +1,35 @@ + + * Copyright (c) 2011 Bart Visscher + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + + +// Check if we are a user +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('contacts'); +OCP\JSON::callCheck(); +require_once('loghandler.php'); + +debug('name: '.$_POST['name']); + +$userid = OCP\USER::getUser(); +$name = isset($_POST['name'])?trim(strip_tags($_POST['name'])):null; +$description = isset($_POST['description'])?trim(strip_tags($_POST['description'])):null; + +if(is_null($name)) { + bailOut('Cannot add addressbook with an empty name.'); +} +$bookid = OC_Contacts_Addressbook::add($userid, $name, $description); +if(!$bookid) { + bailOut('Error adding addressbook: '.$name); +} + +if(!OC_Contacts_Addressbook::setActive($bookid, 1)) { + bailOut('Error activating addressbook.'); +} +$addressbook = OC_Contacts_App::getAddressbook($bookid); +OCP\JSON::success(array('data' => $addressbook)); diff --git a/apps/contacts/ajax/importaddressbook.php b/apps/contacts/ajax/importaddressbook.php deleted file mode 100644 index 6b5b06681c..0000000000 --- a/apps/contacts/ajax/importaddressbook.php +++ /dev/null @@ -1,23 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ - -OCP\JSON::checkLoggedIn(); -OCP\App::checkAppEnabled('contacts'); -$upload_max_filesize = OCP\Util::computerFileSize(ini_get('upload_max_filesize')); -$post_max_size = OCP\Util::computerFileSize(ini_get('post_max_size')); -$maxUploadFilesize = min($upload_max_filesize, $post_max_size); - -$freeSpace=OC_Filesystem::free_space('/'); -$freeSpace=max($freeSpace,0); -$maxUploadFilesize = min($maxUploadFilesize ,$freeSpace); - -$tmpl = new OCP\Template('contacts', 'part.importaddressbook'); -$tmpl->assign('uploadMaxFilesize', $maxUploadFilesize); -$tmpl->assign('requesttoken', $_SERVER['HTTP_REQUESTTOKEN']); -$tmpl->assign('uploadMaxHumanFilesize', OCP\Util::humanFileSize($maxUploadFilesize)); -$tmpl->printpage(); diff --git a/apps/contacts/ajax/selectaddressbook.php b/apps/contacts/ajax/selectaddressbook.php new file mode 100644 index 0000000000..6c35d08c82 --- /dev/null +++ b/apps/contacts/ajax/selectaddressbook.php @@ -0,0 +1,16 @@ + + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +OCP\JSON::checkLoggedIn(); +OCP\JSON::checkAppEnabled('contacts'); + +$addressbooks = OC_Contacts_Addressbook::all(OCP\USER::getUser()); +$tmpl = new OCP\Template("contacts", "part.selectaddressbook"); +$tmpl->assign('addressbooks', $addressbooks); +$page = $tmpl->fetchPage(); +OCP\JSON::success(array('data' => array('page' => $page ))); diff --git a/apps/contacts/ajax/uploadimport.php b/apps/contacts/ajax/uploadimport.php index 80b282f38a..3c5a2d750e 100644 --- a/apps/contacts/ajax/uploadimport.php +++ b/apps/contacts/ajax/uploadimport.php @@ -27,13 +27,16 @@ OCP\JSON::callCheck(); require_once('loghandler.php'); $view = OCP\Files::getStorage('contacts'); +if(!$view->file_exists('imports')) { + $view->mkdir('imports'); +} $tmpfile = md5(rand()); // If it is a Drag'n'Drop transfer it's handled here. $fn = (isset($_SERVER['HTTP_X_FILE_NAME']) ? $_SERVER['HTTP_X_FILE_NAME'] : false); if($fn) { - if($view->file_put_contents('/'.$tmpfile, file_get_contents('php://input'))) { - OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + if($view->file_put_contents('/imports/'.$fn, file_get_contents('php://input'))) { + OCP\JSON::success(array('data' => array('file'=>$tmpfile, 'name'=>$fn))); exit(); } else { bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); @@ -60,10 +63,9 @@ if($error !== UPLOAD_ERR_OK) { } $file=$_FILES['importfile']; -$tmpfname = tempnam(get_temp_dir(), "occOrig"); if(file_exists($file['tmp_name'])) { - if($view->file_put_contents('/'.$tmpfile, file_get_contents($file['tmp_name']))) { - OCP\JSON::success(array('data' => array('path'=>'', 'file'=>$tmpfile))); + if($view->file_put_contents('/imports/'.$file['name'], file_get_contents($file['tmp_name']))) { + OCP\JSON::success(array('data' => array('file'=>$file['name'], 'name'=>$file['name']))); } else { bailOut(OC_Contacts_App::$l10n->t('Error uploading contacts to storage.')); } diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index 5b6ccb7638..ad97b21104 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -13,6 +13,7 @@ .ui-state-hover { border: 1px solid dashed; } #bottomcontrols { padding: 0; bottom:0px; height:2.8em; width: 20em; margin:0; background:#eee; border-top:1px solid #ccc; position:fixed; -moz-box-shadow: 0 -3px 3px -3px #000; -webkit-box-shadow: 0 -3px 3px -3px #000; box-shadow: 0 -3px 3px -3px #000;} #bottomcontrols img { margin-top: 0.35em; } +#uploadprogressbar { display: none; padding: 0; bottom: 3em; height:2em; width: 20em; margin:0; background:#eee; border:1px solid #ccc; position:fixed; } #contacts_newcontact { float: left; margin: 0.2em 0 0 1em; } #chooseaddressbook { float: right; margin: 0.2em 1em 0 0; } #actionbar { position: relative; clear: both; height: 30px;} diff --git a/apps/contacts/import.php b/apps/contacts/import.php index 93c47ef266..3f45e5631f 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -12,7 +12,6 @@ OCP\JSON::checkLoggedIn(); OCP\App::checkAppEnabled('contacts'); session_write_close(); -$cr = "\r"; $nl = "\n"; global $progresskey; @@ -31,7 +30,7 @@ writeProgress('10'); $view = $file = null; if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { $view = OCP\Files::getStorage('contacts'); - $file = $view->file_get_contents('/' . $_POST['file']); + $file = $view->file_get_contents('/imports/' . $_POST['file']); } else { $file = OC_Filesystem::file_get_contents($_POST['path'] . '/' . $_POST['file']); } @@ -56,10 +55,8 @@ if(isset($_POST['method']) && $_POST['method'] == 'new'){ } //analyse the contacts file writeProgress('40'); +$file = str_replace(array("\r","\n\n"), array("\n","\n"), $file); $lines = explode($nl, $file); -if(count($lines) == 1) { // Mac eol - $lines = explode($cr, $file); -} $inelement = false; $parts = array(); diff --git a/apps/contacts/index.php b/apps/contacts/index.php index fbc3565c4d..00b1b4f7a9 100644 --- a/apps/contacts/index.php +++ b/apps/contacts/index.php @@ -42,6 +42,7 @@ OCP\Util::addscript('','oc-vcategories'); OCP\Util::addscript('contacts','contacts'); OCP\Util::addscript('contacts','expanding'); OCP\Util::addscript('contacts','jquery.combobox'); +OCP\Util::addscript('files', 'jquery.fileupload'); OCP\Util::addscript('contacts','jquery.inview'); OCP\Util::addscript('contacts','jquery.Jcrop'); OCP\Util::addscript('contacts','jquery.multi-autocomplete'); diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index b0274201ac..eabc368cf8 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -12,7 +12,7 @@ String.prototype.strip_tags = function(){ Contacts={ UI:{ - notification:function(msg, ndata) { + notify:function(msg, ndata) { $('#notification').text(msg); if(data) { $('#notification').data(ndata[0],ndata[1]); @@ -218,7 +218,7 @@ Contacts={ $('#contacts_deletecard').click( function() { Contacts.UI.Card.doDelete();return false;} ); $('#contacts_deletecard').keydown( function(event) { - if(event.which == 13) { + if(event.which == 13 || event.which == 32) { Contacts.UI.Card.doDelete(); } return false; @@ -226,7 +226,7 @@ Contacts={ $('#contacts_downloadcard').click( function() { Contacts.UI.Card.doExport();return false;} ); $('#contacts_downloadcard').keydown( function(event) { - if(event.which == 13) { + if(event.which == 13 || event.which == 32) { Contacts.UI.Card.doExport(); } return false; @@ -295,22 +295,32 @@ Contacts={ honpre:'', honsuf:'', data:undefined, - update:function(id, bookid) { - var newid, firstitem; - if(!id) { + update:function(params) { // params {cid:int, aid:int} + if(!params) { params = {}; } + $('#contacts li').removeClass('active'); + console.log('Card, cid: ' + params.cid + ' aid: ' + params.aid); + var newid, bookid, firstitem; + if(!parseInt(params.cid) && !parseInt(params.aid)) { firstitem = $('#contacts ul').first().find('li:first-child'); if(firstitem.length > 0) { - newid = firstitem.data('id'); - bookid = firstitem.data('bookid'); + newid = parseInt(firstitem.data('id')); + bookid = parseInt(firstitem.data('bookid')); } + } else if(!parseInt(params.cid) && parseInt(params.aid)) { + bookid = parseInt(params.aid); + newid = parseInt($('#contacts').find('li[data-bookid="'+bookid+'"]').first().data('id')); + } else if(parseInt(params.cid) && !parseInt(params.aid)) { + newid = parseInt(params.cid); + bookid = parseInt($('#contacts li[data-id="'+newid+'"]').data('bookid')); } else { - newid = id; - bookid = bookid?bookid:$('#contacts li[data-id="'+newid+'"]').data('bookid'); + newid = parseInt(params.cid); + bookid = parseInt(params.aid); } - if(!bookid) { - bookid = $('#contacts h3').first().data('id'); + if(!bookid || !newid) { + bookid = parseInt($('#contacts h3').first().data('id')); + newid = parseInt($('#contacts').find('li[data-bookid="'+bookid+'"]').first().data('id')); } - console.log('bookid: ' +bookid); + console.log('newid: ' + newid + ' bookid: ' +bookid); var localLoadContact = function(newid, bookid) { if($('.contacts li').length > 0) { $('#contacts li[data-id="'+newid+'"]').addClass('active'); @@ -359,9 +369,6 @@ Contacts={ doExport:function() { document.location.href = OC.linkTo('contacts', 'export.php') + '?contactid=' + this.id; }, - doImport:function(){ - Contacts.UI.notImplemented(); - }, editNew:function(){ // add a new contact this.id = ''; this.fn = ''; this.fullname = ''; this.givname = ''; this.famname = ''; this.addname = ''; this.honpre = ''; this.honsuf = ''; //Contacts.UI.Card.add(t('contacts', 'Contact')+';'+t('contacts', 'New')+';;;', t('contacts', 'New Contact'), '', true); @@ -454,7 +461,7 @@ Contacts={ this.data = undefined; if($('.contacts li').length > 0) { // Load first in list. - Contacts.UI.Card.update(newid, bookid); + Contacts.UI.Card.update({cid:newid, aid:bookid}); } else { // load intro page $.getJSON(OC.filePath('contacts', 'ajax', 'loadintro.php'),{},function(jsondata){ @@ -1385,7 +1392,6 @@ Contacts={ if(cb) { cb(jsondata.data); } - //Contacts.UI.Contacts.update(); } else { OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); return false; @@ -1420,128 +1426,14 @@ Contacts={ }); } }, - loadImportHandlers:function() { - $('#import_upload_start').change(function(){ - Contacts.UI.Addressbooks.uploadImport(this.files); - }); - $('#importaddressbook_dialog').find('.upload').click(function() { - Contacts.UI.Addressbooks.droptarget.html(t('contacts', 'Uploading...')); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, true); - //$('#import_upload_start').trigger('click'); - //return false; - }); - $('#importaddressbook_dialog').find('.upload').tipsy(); - this.droptarget = $('#import_drop_target'); - $(this.droptarget).bind('dragover',function(event){ - $(event.target).addClass('droppable'); - event.stopPropagation(); - event.preventDefault(); - }); - $(this.droptarget).bind('dragleave',function(event){ - $(event.target).removeClass('droppable'); - }); - $(this.droptarget).bind('drop',function(event){ - event.stopPropagation(); - event.preventDefault(); - $(event.target).removeClass('droppable'); - $(event.target).html(t('contacts', 'Uploading...')); - Contacts.UI.loading(event.target, true); - $.importUpload(event.originalEvent.dataTransfer.files); - }); - - $.importUpload = function(files){ - var file = files[0]; - if(file.size > $('#max_upload').val()){ - OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - return; - } - if(file.type.indexOf('text') != 0) { - OC.dialogs.alert(t('contacts','You have dropped a file type that cannot be imported: ') + file.type, t('contacts','Wrong file type')); - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - return; - } - var xhr = new XMLHttpRequest(); - - if (!xhr.upload) { - OC.dialogs.alert(t('contacts', 'Your browser doesn\'t support AJAX upload. Please upload the contacts file to ownCloud and import that way.'), t('contacts', 'Error')) - } - importUpload = xhr.upload, - xhr.onreadystatechange = function() { - if (xhr.readyState == 4){ - response = $.parseJSON(xhr.responseText); - if(response.status == 'success') { - if(xhr.status == 200) { - Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); - } else { - $(Contacts.UI.Addressbooks.droptarget).html(Contacts.UI.Addressbooks.droptext); - Contacts.UI.loading(Contacts.UI.Addressbooks.droptarget, false); - OC.dialogs.alert(xhr.status + ': ' + xhr.responseText, t('contacts', 'Error')); - } - } else { - OC.dialogs.alert(response.data.message, t('contacts', 'Error')); - } + doImport:function(file, aid){ + $.post(OC.filePath('contacts', '', 'import.php'), { id: aid, file: file, fstype: 'OC_FilesystemView' }, + function(jsondata){ + if(jsondata.status != 'success'){ + Contacts.UI.notify(jsondata.data.message); } - }; - xhr.open('POST', OC.filePath('contacts', 'ajax', 'uploadimport.php') + '?file='+encodeURIComponent(file.name)+'&requesttoken='+requesttoken, true); - xhr.setRequestHeader('Cache-Control', 'no-cache'); - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - xhr.setRequestHeader('X_FILE_NAME', encodeURIComponent(file.name)); - xhr.setRequestHeader('X-File-Size', file.size); - xhr.setRequestHeader('Content-Type', file.type); - xhr.send(file); - } - }, - uploadImport:function(filelist) { - if(!filelist) { - OC.dialogs.alert(t('contacts','No files selected for upload.'), t('contacts', 'Error')); - return; - } - //var file = filelist.item(0); - var file = filelist[0]; - var target = $('#import_upload_target'); - var form = $('#import_upload_form'); - var totalSize=0; - if(file.size > $('#max_upload').val()){ - OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts', 'Error')); - return; - } else { - target.load(function(){ - var response=jQuery.parseJSON(target.contents().text()); - if(response != undefined && response.status == 'success'){ - Contacts.UI.Addressbooks.doImport(response.data.path, response.data.file); - }else{ - OC.dialogs.alert(response.data.message, t('contacts', 'Error')); - } - }); - form.submit(); - } - }, - importAddressbook:function(object){ - var tr = $(document.createElement('tr')) - .load(OC.filePath('contacts', 'ajax', 'importaddressbook.php')); - $(object).closest('tr').after(tr).hide(); - }, - doImport:function(name, file, aid){ - var cImport = function(id, file) { - $.post(OC.filePath('contacts', '', 'import.php'), { id: id, file: file, fstype: 'OC_FilesystemView' }, - function(jsondata){ - if(jsondata.status == 'success'){ - Contacts.UI.Contacts.update(undefined, id); - } else { - OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); - } - }); - } - if(!aid) { - aid = Contacts.UI.Addressbooks.addAddressbook(name, t('contacts', 'Imported address book'), function(addressbook) { - cImport(addressbook.id, file); - }); - } else { - cImport(aid, file); - } + }); + return false; }, submit:function(button, bookid){ var displayname = $("#displayname_"+bookid).val().trim(); @@ -1597,6 +1489,7 @@ Contacts={ if(!added) { $(droplist).append(dragitem.detach()); } + dragitem.attr('data-bookid', droptarget.data('id')) dragitem.data('bookid', droptarget.data('id')); Contacts.UI.Contacts.scrollTo(dragitem.data('id')); } else { @@ -1605,21 +1498,22 @@ Contacts={ }); }, // Reload the contacts list. - update:function(id, aid, start){ - if(!start) { - if(aid) { - $('#contacts h3[data-id="'+aid+'"],#contacts ul[data-id="'+aid+'"]').remove(); + update:function(params){ + if(!params) { params = {}; } + if(!params.start) { + if(params.aid) { + $('#contacts h3[data-id="'+params.aid+'"],#contacts ul[data-id="'+params.aid+'"]').remove(); } else { $('#contacts').empty(); } } self = this; - console.log('update: ' + aid + ' ' + start); + console.log('update: ' + params.cid + ' ' + params.aid + ' ' + params.start); var firstrun = false; var opts = {}; - opts['startat'] = (start?start:0); - if(aid) { - opts['aid'] = aid; + opts['startat'] = (params.start?params.start:0); + if(params.aid) { + opts['aid'] = params.aid; } $.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),opts,function(jsondata){ if(jsondata.status == 'success'){ @@ -1661,7 +1555,7 @@ Contacts={ var numsiblings = $('.contacts li[data-bookid="'+bookid+'"]').length; if (isInView && numsiblings >= self.batchnum) { console.log('This would be a good time to load more contacts.'); - Contacts.UI.Contacts.update(id, bookid, $('#contacts li[data-bookid="'+bookid+'"]').length); + Contacts.UI.Contacts.update({cid:params.cid, aid:bookid, start:$('#contacts li[data-bookid="'+bookid+'"]').length}); } }); } @@ -1680,7 +1574,7 @@ Contacts={ $('#contacts h3').first().addClass('active'); } if(opts['startat'] == 0) { // only update card on first load. - Contacts.UI.Card.update(); + Contacts.UI.Card.update(params); } } else{ @@ -1720,7 +1614,7 @@ $(document).ready(function(){ // Load a contact. $('.contacts').keydown(function(event) { - if(event.which == 13) { + if(event.which == 13 || event.which == 32) { $('.contacts').click(); } }); @@ -1747,34 +1641,11 @@ $(document).ready(function(){ return false; }); - /*$('.contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) { - if (isInView) { //NOTE: I've kept all conditions for future reference ;-) - // element is now visible in the viewport - if (visiblePartY == 'top') { - // top part of element is visible - } else if (visiblePartY == 'bottom') { - // bottom part of element is visible - } else { - // whole part of element is visible - if (!$(this).find('a').attr('style')) { - //alert($(this).data('id') + ' has background: ' + $(this).attr('style')); - $(this).find('a').css('background','url('+OC.filePath('contacts', '', 'thumbnail.php')+'?id='+$(this).data('id')+') no-repeat'); - }// else { - // alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url')); - //} - } - } else { - // element has gone out of viewport - } - });*/ - $('.contacts_property').live('change', function(){ Contacts.UI.Card.saveProperty(this); }); - /** - * Upload function for dropped files. Should go in the Contacts class/object. - */ + // Upload function for dropped contact photos files. Should go in the Contacts class/object. $.fileUpload = function(files){ var file = files[0]; if(file.size > $('#max_upload').val()){ @@ -1822,21 +1693,32 @@ $(document).ready(function(){ xhr.send(file); } + $(document).bind('drop dragover', function (e) { + e.preventDefault(); // prevent browser from doing anything, if file isn't dropped in dropZone + }); + + //add multiply file upload attribute to all browsers except konqueror (which crashes when it's used) + if(navigator.userAgent.search(/konqueror/i)==-1){ + $('#import_upload_start').attr('multiple','multiple') + } // Import using jquery.fileupload $(function() { - $('#contacts_import').click(function() { + var uploadingFiles = {}, numfiles = 0, uploadedfiles = 0, retries = 0; + var aid; + + $('#contacts_import').click(function() { // TODO: Trick IE by hiding fileupload behind button. $('#import_upload_start').click(); return false; }); $('#import_upload_start').fileupload({ - dropZone: $('#contacts'), // restrict dropZone to content div + dropZone: $('#contacts'), // restrict dropZone to contacts list. add: function(e, data) { var files = data.files; var totalSize=0; - if(files){ - for(var i=0;i$('#max_upload').val()){ - console.log('upload too large'); + OC.dialogs.alert(t('contacts','The file you are trying to upload exceed the maximum size for file uploads on this server.'), t('contacts','Upload too large')); + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + return; }else{ if($.support.xhrFileUpload) { - // TODO: First upload file(s) and cache names in an array, then check if we know - // the aid, otherwise ask user, then import files. for(var i=0;i tr').not('[data-mime]').fadeOut(); - $('#fileList > tr').not('[data-mime]').remove(); + Contacts.UI.notify(response.data.message); } }); } @@ -1924,16 +1788,11 @@ $(document).ready(function(){ console.log('fail'); // TODO: cancel upload & display error notification }, - progress: function(e, data) { - // TODO: show nice progress bar in file row - }, progressall: function(e, data) { - var progress = (data.loaded/data.total)*100; - console.log('progress: ' + progress); + var progress = (data.loaded/data.total)*50; $('#uploadprogressbar').progressbar('value',progress); }, start: function(e, data) { - console.log('start'); $('#uploadprogressbar').progressbar({value:0}); $('#uploadprogressbar').fadeIn(); if(data.dataType != 'iframe ') { @@ -1941,16 +1800,104 @@ $(document).ready(function(){ } }, stop: function(e, data) { - console.log('stop'); + // stop only gets fired once so we collect uploaded items here. + var importFiles = function(aid, fileList) { + // Create a closure that can be called from different places. + if(numfiles != uploadedfiles) { + Contacts.UI.notify('Not all files uploaded. Retrying...'); + retries += 1; + if(retries > 0) { + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + OC.dialogs.alert(t('contacts', 'Something went wrong with the upload, please retry.'), t('contacts', 'Error')); + return; + } + setTimeout(function() { // Just to let any uploads finish + importFiles(aid, uploadingFiles); + }, 1000); + } + $('#uploadprogressbar').progressbar('value',50); + var todo = uploadedfiles; + $.each(fileList, function(fileName, data) { + Contacts.UI.Addressbooks.doImport(fileName, aid); + delete fileList[fileName]; + numfiles -= 1; uploadedfiles -= 1; + $('#uploadprogressbar').progressbar('value',50+(50/(todo-uploadedfiles))); + }) + $('#uploadprogressbar').progressbar('value',100); + $('#uploadprogressbar').fadeOut(); + setTimeout(function() { + Contacts.UI.Contacts.update({aid:aid}); + numfiles = uploadedfiles = retries = aid = 0; + }, 1000); + } + if(!aid) { + // Either selected with filepicker or dropped outside of an address book. + $.getJSON(OC.filePath('contacts', 'ajax', 'selectaddressbook.php'),{},function(jsondata) { + if(jsondata.status == 'success') { + if($('#selectaddressbook_dialog').dialog('isOpen') == true) { + $('#selectaddressbook_dialog').dialog('moveToTop'); + } else { + $('#dialog_holder').html(jsondata.data.page).ready(function($) { + $('#selectaddressbook_dialog').dialog({ + modal: true, height: 'auto', width: 'auto', + buttons: { + 'Ok':function() { + aid = $('#selectaddressbook_dialog').find('input:checked').val(); + if(aid == 'new') { + var displayname = $('#selectaddressbook_dialog').find('input.name').val(); + var description = $('#selectaddressbook_dialog').find('input.desc').val(); + if(!displayname.trim()) { + OC.dialogs.alert(t('contacts', 'The address book name cannot be empty.'), t('contacts', 'Error')); + return false; + } + $(this).dialog('close'); + Contacts.UI.Addressbooks.addAddressbook(displayname, description, function(addressbook){ + aid = addressbook.id; + setTimeout(function() { + importFiles(aid, uploadingFiles); + }, 500); + console.log('aid ' + aid); + }); + } else { + setTimeout(function() { + importFiles(aid, uploadingFiles); + }, 500); + console.log('aid ' + aid); + $(this).dialog('close'); + } + }, + 'Cancel':function() { + $(this).dialog('close'); + numfiles = uploadedfiles = retries = aid = 0; + uploadingFiles = {}; + $('#uploadprogressbar').fadeOut(); + } + }, + close: function(event, ui) { + // TODO: If numfiles != 0 delete tmp files after a timeout. + $(this).dialog('destroy').remove(); + } + }); + }); + } + } else { + OC.dialogs.alert(jsondata.data.message, t('contacts', 'Error')); + } + }); + } else { + // Dropped on an address book or it's list. + setTimeout(function() { // Just to let any uploads finish + importFiles(aid, uploadingFiles); + }, 1000); + } if(data.dataType != 'iframe ') { $('#upload input.stop').hide(); } - $('#uploadprogressbar').progressbar('value',100); - $('#uploadprogressbar').fadeOut(); } }) }); Contacts.UI.loadHandlers(); - Contacts.UI.Contacts.update(id); + Contacts.UI.Contacts.update({cid:id}); }); diff --git a/apps/contacts/lib/app.php b/apps/contacts/lib/app.php index f125ec0293..046ceb0bf0 100644 --- a/apps/contacts/lib/app.php +++ b/apps/contacts/lib/app.php @@ -41,7 +41,7 @@ class OC_Contacts_App { $card = OC_Contacts_VCard::find( $id ); if( $card === false ) { OCP\Util::writeLog('contacts', 'Contact could not be found: '.$id, OCP\Util::ERROR); - OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.$id))); + OCP\JSON::error(array('data' => array( 'message' => self::$l10n->t('Contact could not be found.').' '.print_r($id, true)))); exit(); } diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index 5b49b68e95..e13748ddde 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -1,3 +1,4 @@ +
@@ -27,3 +36,7 @@
+ + + + diff --git a/apps/contacts/templates/part.chooseaddressbook.php b/apps/contacts/templates/part.chooseaddressbook.php index a0ec053ab9..caed67736c 100644 --- a/apps/contacts/templates/part.chooseaddressbook.php +++ b/apps/contacts/templates/part.chooseaddressbook.php @@ -14,7 +14,6 @@ for($i = 0; $i < count($option_addressbooks); $i++){ t('New Address Book') ?> - t('Import from VCF') ?> diff --git a/apps/contacts/templates/part.importaddressbook.php b/apps/contacts/templates/part.importaddressbook.php deleted file mode 100644 index 8ceb5f3538..0000000000 --- a/apps/contacts/templates/part.importaddressbook.php +++ /dev/null @@ -1,38 +0,0 @@ - - * This file is licensed under the Affero General Public License version 3 or - * later. - * See the COPYING-README file. - */ -?> - - - - - - -
t('Select address book to import to:') ?> -
- - - t("Drop a VCF file
to import contacts."); ?> (Max. )
- - - -
-
- -"> - - - \ No newline at end of file diff --git a/apps/contacts/templates/part.selectaddressbook.php b/apps/contacts/templates/part.selectaddressbook.php new file mode 100644 index 0000000000..c54ddaf2e6 --- /dev/null +++ b/apps/contacts/templates/part.selectaddressbook.php @@ -0,0 +1,27 @@ +
"> +
+ + $addressbook) { ?> + + + + + + + + + + + +
+ > + + +
+ + + " /> + " />
+
+
+ From ce40576881b2a0894f873ad40adb43187994b5a7 Mon Sep 17 00:00:00 2001 From: Thomas Mueller Date: Sun, 15 Jul 2012 12:05:48 +0200 Subject: [PATCH 23/31] MySql testing added --- autotest.sh | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/autotest.sh b/autotest.sh index a9794db698..06605687d1 100755 --- a/autotest.sh +++ b/autotest.sh @@ -1,4 +1,6 @@ -#preparation +# +# sqlite testing now +# echo "Setup environment for sqlite testing ..." DATADIR=data-autotest rm -rf $DATADIR @@ -25,8 +27,46 @@ echo 'Testing with sqlite ...' cd tests php -f index.php -- xml > autotest-results-sqlite.xml +# +# mysql testing now +# +# NOTES: +# - grant access permissions: grant all on oc_autotest.* to 'oc_autotest'@'localhost'; +# +echo "Setup environment for MySql testing ..." +DATADIR=data-autotest +rm -rf $DATADIR +mkdir $DATADIR +rm -rf config/config.php +cat > ./config/autoconfig.php < false, + 'dbtype' => 'mysql', + 'dbtableprefix' => 'oc_', + 'datadirectory' => 'data', + 'adminlogin' => 'admin', + 'adminpass' => 'admin', + 'directory' => '$PWD/$DATADIR', + 'dbuser' => 'oc_autotest', + 'dbname' => 'oc_autotest', + 'dbhost' => 'localhost', + 'dbpass' => 'owncloud', +); +DELIM + +#drop the database +mysql -u oc_autotest -powncloud -e "DROP DATABASE oc_autotest" + +#setup +php -f index.php + +#test execution +echo 'Testing with MySql ...' +cd tests +php -f index.php -- xml > autotest-results-MySql.xml # -# TODO: create config for mysql and postgres +# TODO: create config for postgres # From 287285880c0ed61f0b247b2cdef97cc75cf4b0a2 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 09:33:33 +0200 Subject: [PATCH 24/31] Removed obsolete TODO. --- apps/contacts/js/contacts.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index eabc368cf8..25739cc974 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -187,16 +187,7 @@ Contacts={ } ] ); - /*$('#fn').blur(function(){ - if($('#fn').val() == '') { - OC.dialogs.alert(t('contacts','The name field cannot be empty. Please enter a name for this contact.'), t('contacts','Name is empty'), function() { $('#fn').focus(); }); - $('#fn').focus(); - return false; - } - });*/ - // Name has changed. Update it and reorder. - // TODO: Take addressbook into account $('#fn').change(function(){ var name = $('#fn').val().strip_tags(); var item = $('.contacts li[data-id="'+Contacts.UI.Card.id+'"]'); From 4e684b9e9dd7c31e04d65e506dfe6e0bb0eaccdb Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 09:54:31 +0200 Subject: [PATCH 25/31] Fixed sorting of addressbooks. --- apps/contacts/js/contacts.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 25739cc974..a9fe38ead1 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1509,16 +1509,26 @@ Contacts={ $.getJSON(OC.filePath('contacts', 'ajax', 'contacts.php'),opts,function(jsondata){ if(jsondata.status == 'success'){ var books = jsondata.data.entries; - $.each(jsondata.data.entries, function(b, book) { + $.each(books, function(b, book) { if($('#contacts h3[data-id="'+b+'"]').length == 0) { firstrun = true; - // TODO: Make sure address books are sorted properly. if($('#contacts h3').length == 0) { $('#contacts').html('

'+book.displayname+'

'); } else { if(!$('#contacts h3[data-id="'+b+'"]').length) { - $('

'+book.displayname+'

') - .appendTo('#contacts'); + var item = $('

'+book.displayname+'

') + var added = false; + $('#contacts h3').each(function(){ + if ($(this).text().toLowerCase() > book.displayname.toLowerCase()) { + $(this).before(item).fadeIn('fast'); + added = true; + return false; + } + }); + if(!added) { + $('#contacts').append(item); + } + } } $('#contacts h3[data-id="'+b+'"]').on('click', function(event) { From 7af608881bb1ae8f3b08cae63a0e4b03891f1ed5 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 10:12:47 +0200 Subject: [PATCH 26/31] Added notification. --- apps/contacts/js/contacts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index a9fe38ead1..f859f8385c 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1787,7 +1787,8 @@ $(document).ready(function(){ }, fail: function(e, data) { console.log('fail'); - // TODO: cancel upload & display error notification + Contacts.UI.notify(data.errorThrown + ': ' + data.textStatus); + // TODO: Remove file from upload queue. }, progressall: function(e, data) { var progress = (data.loaded/data.total)*50; From d71da67bee465585d0873879753c3d3a8d5b5166 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 10:24:33 +0200 Subject: [PATCH 27/31] Typo. --- apps/contacts/import.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contacts/import.php b/apps/contacts/import.php index 3f45e5631f..e6d1e8050d 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -79,7 +79,7 @@ writeProgress('70'); $imported = 0; $failed = 0; if(!count($parts) > 0) { - OCP\JSON::error(array('data' => array('message' => 'No contacts to import in .'.$_POST['file'].' Please check if the file is corrupted.'))); + OCP\JSON::error(array('data' => array('message' => 'No contacts to import in '.$_POST['file'].'. Please check if the file is corrupted.'))); exit(); } foreach($parts as $part){ From 48521fcfaa6d6b36f5e55ac5de936b82a8f60c19 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 10:29:03 +0200 Subject: [PATCH 28/31] Made notifications more flexible. --- apps/contacts/js/contacts.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index f859f8385c..ffbc1d009e 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -12,13 +12,10 @@ String.prototype.strip_tags = function(){ Contacts={ UI:{ - notify:function(msg, ndata) { - $('#notification').text(msg); - if(data) { - $('#notification').data(ndata[0],ndata[1]); - } + notify:function(params) { + $('#notification').text(params.message); $('#notification').fadeIn(); - setTimeout($('#notification').fadeOut(), 10000); + setTimeout(function() {$('#notification').fadeOut();}, 10000); }, notImplemented:function() { OC.dialogs.alert(t('contacts', 'Sorry, this functionality has not been implemented yet'), t('contacts', 'Not implemented')); @@ -1421,7 +1418,7 @@ Contacts={ $.post(OC.filePath('contacts', '', 'import.php'), { id: aid, file: file, fstype: 'OC_FilesystemView' }, function(jsondata){ if(jsondata.status != 'success'){ - Contacts.UI.notify(jsondata.data.message); + Contacts.UI.notify({message:jsondata.data.message}); } }); return false; @@ -1757,12 +1754,12 @@ $(document).ready(function(){ // import the file uploadedfiles += 1; } else { - Contacts.UI.notify(jsondata.data.message); + Contacts.UI.notify({message:jsondata.data.message}); } return false; }) .error(function(jqXHR, textStatus, errorThrown) { - Contacts.UI.notify(errorThrown + ': ' + textStatus); + Contacts.UI.notify({message:errorThrown + ': ' + textStatus,}); }); uploadingFiles[fileName] = jqXHR; } @@ -1779,7 +1776,7 @@ $(document).ready(function(){ } FileList.loadingDone(file.name); } else { - Contacts.UI.notify(response.data.message); + Contacts.UI.notify({message:response.data.message}); } }); } @@ -1787,7 +1784,7 @@ $(document).ready(function(){ }, fail: function(e, data) { console.log('fail'); - Contacts.UI.notify(data.errorThrown + ': ' + data.textStatus); + Contacts.UI.notify({message:data.errorThrown + ': ' + data.textStatus}); // TODO: Remove file from upload queue. }, progressall: function(e, data) { @@ -1806,7 +1803,7 @@ $(document).ready(function(){ var importFiles = function(aid, fileList) { // Create a closure that can be called from different places. if(numfiles != uploadedfiles) { - Contacts.UI.notify('Not all files uploaded. Retrying...'); + Contacts.UI.notify({message:t('contacts', 'Not all files uploaded. Retrying...')}); retries += 1; if(retries > 0) { numfiles = uploadedfiles = retries = aid = 0; From 8b49e304e0729b464975add486f527484cbfa7fb Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 12:20:26 +0200 Subject: [PATCH 29/31] Hide file form field behind image so it will maybe work with IE... --- apps/contacts/css/contacts.css | 4 ++-- apps/contacts/js/contacts.js | 6 ++---- apps/contacts/templates/index.php | 12 ++++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/contacts/css/contacts.css b/apps/contacts/css/contacts.css index ad97b21104..de7950ecc6 100644 --- a/apps/contacts/css/contacts.css +++ b/apps/contacts/css/contacts.css @@ -14,7 +14,7 @@ #bottomcontrols { padding: 0; bottom:0px; height:2.8em; width: 20em; margin:0; background:#eee; border-top:1px solid #ccc; position:fixed; -moz-box-shadow: 0 -3px 3px -3px #000; -webkit-box-shadow: 0 -3px 3px -3px #000; box-shadow: 0 -3px 3px -3px #000;} #bottomcontrols img { margin-top: 0.35em; } #uploadprogressbar { display: none; padding: 0; bottom: 3em; height:2em; width: 20em; margin:0; background:#eee; border:1px solid #ccc; position:fixed; } -#contacts_newcontact { float: left; margin: 0.2em 0 0 1em; } +#contacts_newcontact, #contacts_import, #chooseaddressbook { float: left; margin: 0.2em 0 0 1em; border: 0 none; border-radius: 0; -moz-box-shadow: none; box-shadow: none; outline: 0 none; } #chooseaddressbook { float: right; margin: 0.2em 1em 0 0; } #actionbar { position: relative; clear: both; height: 30px;} #contacts_deletecard {position:relative; float:left; background:url('%webroot%/core/img/actions/delete.svg') no-repeat center; } @@ -111,7 +111,7 @@ dl.addresscard .action { float: right; } #file_upload_form { width: 0; height: 0; } #file_upload_target, #import_upload_target, #crop_target { display:none; } #file_upload_start, #import_upload_start { -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter:alpha(opacity=0); opacity:0; z-index:1001; width:0; height:0;} -#import_upload_start { width: 16px; height: 16px; margin: 0 0 0 0; } +#import_upload_start { width: 20px; height: 20px; margin: 0 0 -24px 0; padding: 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; } diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index ffbc1d009e..2ebec4c242 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1704,12 +1704,9 @@ $(document).ready(function(){ var uploadingFiles = {}, numfiles = 0, uploadedfiles = 0, retries = 0; var aid; - $('#contacts_import').click(function() { // TODO: Trick IE by hiding fileupload behind button. - $('#import_upload_start').click(); - return false; - }); $('#import_upload_start').fileupload({ dropZone: $('#contacts'), // restrict dropZone to contacts list. + acceptFileTypes: /^text\/(directory|vcard|x-vcard)$/i, add: function(e, data) { var files = data.files; var totalSize=0; @@ -1759,6 +1756,7 @@ $(document).ready(function(){ return false; }) .error(function(jqXHR, textStatus, errorThrown) { + console.log(textStatus); Contacts.UI.notify({message:errorThrown + ': ' + textStatus,}); }); uploadingFiles[fileName] = jqXHR; diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index e13748ddde..98cb67a26e 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -11,13 +11,13 @@
-
- - - -
- + + + + <?php echo $l->t('Import'); ?> + +
From db034f05ca17a961f99e7eb7033ac38d2615a577 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 12:22:14 +0200 Subject: [PATCH 30/31] Improve temp file handling. --- apps/contacts/import.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/contacts/import.php b/apps/contacts/import.php index e6d1e8050d..ed1b80e132 100644 --- a/apps/contacts/import.php +++ b/apps/contacts/import.php @@ -48,7 +48,7 @@ if(isset($_POST['method']) && $_POST['method'] == 'new'){ }else{ $id = $_POST['id']; if(!$id) { - OCP\JSON::error(array('data' => array('message' => 'Error getting the ID of the address book.'))); + OCP\JSON::error(array('data' => array('message' => 'Error getting the ID of the address book.', 'file'=>$_POST['file']))); exit(); } OC_Contacts_App::getAddressbook($id); // is owner access check @@ -79,7 +79,7 @@ writeProgress('70'); $imported = 0; $failed = 0; if(!count($parts) > 0) { - OCP\JSON::error(array('data' => array('message' => 'No contacts to import in '.$_POST['file'].'. Please check if the file is corrupted.'))); + OCP\JSON::error(array('data' => array('message' => 'No contacts to import in '.$_POST['file'].'. Please check if the file is corrupted.', 'file'=>$_POST['file']))); exit(); } foreach($parts as $part){ @@ -102,8 +102,8 @@ writeProgress('100'); sleep(3); OC_Cache::remove($progresskey); if(isset($_POST['fstype']) && $_POST['fstype'] == 'OC_FilesystemView') { - if(!$view->unlink('/' . $_POST['file'])) { + if(!$view->unlink('/imports/' . $_POST['file'])) { OCP\Util::writeLog('contacts','Import: Error unlinking OC_FilesystemView ' . '/' . $_POST['file'], OCP\Util::ERROR); } } -OCP\JSON::success(array('data' => array('imported'=>$imported, 'failed'=>$failed))); +OCP\JSON::success(array('data' => array('imported'=>$imported, 'failed'=>$failed, 'file'=>$_POST['file']))); From 160e701fbf4d87e9673114f0dd51c6705e180475 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Sun, 15 Jul 2012 12:27:46 +0200 Subject: [PATCH 31/31] Make list droppable too instead of just the header. --- apps/contacts/js/contacts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contacts/js/contacts.js b/apps/contacts/js/contacts.js index 2ebec4c242..b4e7cdba44 100644 --- a/apps/contacts/js/contacts.js +++ b/apps/contacts/js/contacts.js @@ -1535,7 +1535,7 @@ Contacts={ return false; }); var accept = 'li:not([data-bookid="'+b+'"])'; - $('#contacts h3[data-id="'+b+'"]').droppable({ + $('#contacts h3[data-id="'+b+'"],#contacts ul[data-id="'+b+'"]').droppable({ drop: Contacts.UI.Contacts.drop, activeClass: 'ui-state-hover', accept: accept