Commit bf2e360283d89b553fbadf1c9b0a5dfc6a89fbb8

Authored by Megan Watson
1 parent 73a11d7d

KTS-2672

"KTWebDAV move functions fail on litmus"
Fixed. Corrected status messages. Adjusted rename to check for overwrite.

KTS-2671
"KTWebDAV copy functions fail on litmus"
Fixed. Corrected status messages. Added extra depth of '0'. Changed documentutil to accept a new document or folder name. Changed folderutil to allow a copy of only the folder, ignoring all subfolders and documents.

BBS-1119
"Refactor move functions into ktapi"
In progress. Cleaned up some functionality. Added in line documentation.

BBS-1118
"Refactor copy functions into ktapi"
In progress. Added in line documentation.



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@7667 c91229c3-7414-0410-bfa2-8a42b809f60b
ktwebdav/lib/KTWebDAVServer.inc.php
@@ -1132,9 +1132,10 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1132,9 +1132,10 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1132 1132
1133 /** 1133 /**
1134 * GET method helper 1134 * GET method helper
  1135 + * Method takes a directory path and checks whether it refers to a document or folder. The relevant folder and/or document id is returned.
1135 * 1136 *
1136 - * @param string directory path  
1137 - * @return array or false 1137 + * @param $path string The directory path
  1138 + * @return array or bool Either returns an array of folder/document id's or false if an error occurred
1138 */ 1139 */
1139 function _folderOrDocument($path) { 1140 function _folderOrDocument($path) {
1140 1141
@@ -1142,14 +1143,14 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1142,14 +1143,14 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1142 1143
1143 $this->ktwebdavLog("Entering _folderOrDocument. path is " . $path, 'info', true); 1144 $this->ktwebdavLog("Entering _folderOrDocument. path is " . $path, 'info', true);
1144 1145
1145 - if ( !(strstr($path,"__BAOBABCLIENT__") === false) ) {  
1146 - return array(0, 1);  
1147 - }  
1148 - 1146 + /* ** Get the directory path and the folder/document being acted on ** */
1149 $sFileName = basename($path); 1147 $sFileName = basename($path);
1150 // for windows replace backslash with forwardslash 1148 // for windows replace backslash with forwardslash
1151 $sFolderPath = str_replace("\\", '/', dirname($path) ); 1149 $sFolderPath = str_replace("\\", '/', dirname($path) );
1152 1150
  1151 + /* ** Get the starting point for recursing through the directory structure
  1152 + FolderId = 0 if we're in the root folder
  1153 + FolderId = 1 the starting point for locating any other folder ** */
1153 if ($sFolderPath == "/" || $sFolderPath == "/ktwebdav") { 1154 if ($sFolderPath == "/" || $sFolderPath == "/ktwebdav") {
1154 $this->ktwebdavLog("This is the root folder.", 'info', true); 1155 $this->ktwebdavLog("This is the root folder.", 'info', true);
1155 $sFolderPath = $this->rootFolder; 1156 $sFolderPath = $this->rootFolder;
@@ -1164,6 +1165,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1164,6 +1165,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1164 $this->ktwebdavLog("sFolderName is " . $sFolderPath, 'info', true); 1165 $this->ktwebdavLog("sFolderName is " . $sFolderPath, 'info', true);
1165 $this->ktwebdavLog("iFolderID is " . $iFolderID, 'info', true); 1166 $this->ktwebdavLog("iFolderID is " . $iFolderID, 'info', true);
1166 1167
  1168 + /* ** Break up the directory path into its component directory's,
  1169 + recurse through the directory's to find the correct id of the current directory.
  1170 + Avoids situations where several directory's have the same name. ** */
1167 $aFolderNames = split('/', $sFolderPath); 1171 $aFolderNames = split('/', $sFolderPath);
1168 1172
1169 $this->ktwebdavLog("aFolderNames are: " . print_r($aFolderNames, true), 'info', true); 1173 $this->ktwebdavLog("aFolderNames are: " . print_r($aFolderNames, true), 'info', true);
@@ -1196,6 +1200,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1196,6 +1200,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1196 $this->ktwebdavLog("iFolderID set to " . $iFolderID, 'info', true); 1200 $this->ktwebdavLog("iFolderID set to " . $iFolderID, 'info', true);
1197 } 1201 }
1198 1202
  1203 + /* ** Get the document id using the basename and parent folder id as parameters.
  1204 + If an id is obtained then the path refers to a document.
  1205 + If no id is returned then the path refers to a folder or a non-existing document. ** */
1199 // FIXME: Direct database access 1206 // FIXME: Direct database access
1200 // $sQuery = "SELECT id FROM documents WHERE folder_id = ? AND filename = ? AND status_id = 1"; 1207 // $sQuery = "SELECT id FROM documents WHERE folder_id = ? AND filename = ? AND status_id = 1";
1201 $sQuery = "SELECT D.id "; 1208 $sQuery = "SELECT D.id ";
@@ -1214,12 +1221,18 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1214,12 +1221,18 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1214 return false; 1221 return false;
1215 } 1222 }
1216 1223
  1224 + /* ** If the path refers to a folder or a non-existing document,
  1225 + Get the folder id using the basename and parent folder id as parameters.
  1226 + If an id is obtained then the path refers to an existing folder.
  1227 + If no id is returned and the basename is empty then path refers to the root folder.
  1228 + If no id is returned and the basename is not empty, then the path refers to either a non-existing folder or document. ** */
1217 if ($iDocumentID === null) { 1229 if ($iDocumentID === null) {
1218 $this->ktwebdavLog("iDocumentID is null", 'info', true); 1230 $this->ktwebdavLog("iDocumentID is null", 'info', true);
1219 // FIXME: Direct database access 1231 // FIXME: Direct database access
1220 $sQuery = "SELECT id FROM folders WHERE parent_id = ? AND name = ?"; 1232 $sQuery = "SELECT id FROM folders WHERE parent_id = ? AND name = ?";
1221 $aParams = array($iFolderID, $sFileName); 1233 $aParams = array($iFolderID, $sFileName);
1222 $id = DBUtil::getOneResultKey(array($sQuery, $aParams), 'id'); 1234 $id = DBUtil::getOneResultKey(array($sQuery, $aParams), 'id');
  1235 +
1223 if (PEAR::isError($id)) { 1236 if (PEAR::isError($id)) {
1224 $this->ktwebdavLog("A DB(2) error occurred in _folderOrDocument", 'info', true); 1237 $this->ktwebdavLog("A DB(2) error occurred in _folderOrDocument", 'info', true);
1225 return false; 1238 return false;
@@ -1235,6 +1248,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1235,6 +1248,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1235 $this->ktwebdavLog("Setting Location Header to " . "Location: " . $_SERVER["PHP_SELF"] . "/", 'info', true); 1248 $this->ktwebdavLog("Setting Location Header to " . "Location: " . $_SERVER["PHP_SELF"] . "/", 'info', true);
1236 header("Location: " . $_SERVER["PHP_SELF"] . "/"); 1249 header("Location: " . $_SERVER["PHP_SELF"] . "/");
1237 } 1250 }
  1251 + $this->ktwebdavLog("DEBUG: return id ".$id, 'info', true);
1238 return array($id, null); 1252 return array($id, null);
1239 } 1253 }
1240 1254
@@ -1647,24 +1661,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1647,24 +1661,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1647 1661
1648 /** 1662 /**
1649 * MOVE method handler 1663 * MOVE method handler
  1664 + * Method checks if the source path refers to a document / folder then calls the appropriate method handler.
1650 * 1665 *
1651 - * @param array parameter passing array 1666 + * @param $options array parameter passing array
1652 * @return string HTTP status code or false 1667 * @return string HTTP status code or false
1653 */ 1668 */
1654 function MOVE($options) 1669 function MOVE($options)
1655 { 1670 {
1656 - // Use the WebDAV standards way.  
1657 - // See rfc2518 Section 8.9  
1658 - // This does a copy with delete  
1659 - // FIXME: This way does not retain document history and other info  
1660 -  
1661 - //return $this->COPY($options, true);  
1662 -  
1663 - // Use the KT way.  
1664 - // FIXME: This way does not allow overwrite  
1665 -  
1666 $this->ktwebdavLog("Entering MOVE. options are " . print_r($options, true), 'info', true); 1671 $this->ktwebdavLog("Entering MOVE. options are " . print_r($options, true), 'info', true);
1667 1672
  1673 + /* ** Check that write is allowed ** */
1668 if ($this->checkSafeMode()) { 1674 if ($this->checkSafeMode()) {
1669 1675
1670 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet 1676 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
@@ -1679,6 +1685,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1679,6 +1685,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1679 } 1685 }
1680 */ 1686 */
1681 1687
  1688 + /* ** Get the path to the document/folder to be copied.
  1689 + Call function to check if the path refers to a document or a folder.
  1690 + Return 404 error if the path is invalid. ** */
1682 $source_path = $options["path"]; 1691 $source_path = $options["path"];
1683 1692
1684 // Fix for Mac Goliath 1693 // Fix for Mac Goliath
@@ -1710,22 +1719,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1710,22 +1719,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1710 return "404 Not found - Document was not found."; 1719 return "404 Not found - Document was not found.";
1711 } 1720 }
1712 1721
  1722 + /* ** Get the returned parent folder id and document/folder id.
  1723 + If the parent folder id is false, return 404 error.
  1724 + If the document id is either false or null, then the source is a folder.
  1725 + If the document id exists then the source is a document.
  1726 + If the source is a folder then call _MOVEFolder.
  1727 + If the source is a document then check if its checked out and call _MOVEDocument. ** */
1713 list($iFolderID, $iDocumentID) = $source_res; 1728 list($iFolderID, $iDocumentID) = $source_res;
1714 - if ($iDocumentID === false) { 1729 + if ($iFolderID === false && ($iDocumentID === false || is_null($iDocumentID))) {
1715 $this->ktwebdavLog("404 Not found - Folder was not found.", 'info', true); 1730 $this->ktwebdavLog("404 Not found - Folder was not found.", 'info', true);
1716 return "404 Not found - Folder was not found."; 1731 return "404 Not found - Folder was not found.";
1717 } 1732 }
1718 1733
1719 - if (is_null($iDocumentID)) { 1734 + if (is_null($iDocumentID) || $iDocumentID === false) {
1720 // Source is a folder 1735 // Source is a folder
  1736 + $this->ktwebdavLog("Source is a Folder.", 'info', true);
1721 $movestat = $this->_MOVEFolder($options, $iFolderID); 1737 $movestat = $this->_MOVEFolder($options, $iFolderID);
1722 1738
1723 } else { 1739 } else {
1724 // Source is a document 1740 // Source is a document
  1741 + $this->ktwebdavLog("Source is a Document.", 'info', true);
1725 if ($this->canCopyMoveRenameDocument($iDocumentID)) { 1742 if ($this->canCopyMoveRenameDocument($iDocumentID)) {
1726 $movestat = $this->_MOVEDocument($options, $iFolderID, $iDocumentID); 1743 $movestat = $this->_MOVEDocument($options, $iFolderID, $iDocumentID);
1727 } else { 1744 } else {
1728 - return "Cannot MOVE document because it is checked out by another user."; 1745 + return "423 Locked - Cannot MOVE document because it is checked out by another user.";
1729 } 1746 }
1730 } 1747 }
1731 1748
@@ -1746,7 +1763,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1746,7 +1763,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1746 */ 1763 */
1747 function _MOVEDocument($options, $iFolderID, $iDocumentID) { 1764 function _MOVEDocument($options, $iFolderID, $iDocumentID) {
1748 1765
  1766 + /* ** Ensure that the destination path exists ** */
1749 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"])); 1767 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
  1768 + $this->ktwebdavLog("Entering _MOVEDocument. options are " . print_r($options, true), 'info', true);
1750 1769
1751 // Fix for Mac Goliath 1770 // Fix for Mac Goliath
1752 // Modified - 25/10/07 - remove ktwebdav from document path 1771 // Modified - 25/10/07 - remove ktwebdav from document path
@@ -1760,11 +1779,11 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1760,11 +1779,11 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1760 } 1779 }
1761 } 1780 }
1762 1781
1763 - $this->ktwebdavLog("Entering _MOVEDocument. options are " . print_r($options, true), 'info', true);  
1764 global $default; 1782 global $default;
1765 $new = true; 1783 $new = true;
1766 - //FIXME: refactor me into KTDocumentUtil  
1767 1784
  1785 + /* ** Get the relevant paths. Get the basename of the destination path as the destination filename.
  1786 + Check whether the destination path refers to a folder / document. ** */
1768 $oDocument = Document::get($iDocumentID); 1787 $oDocument = Document::get($iDocumentID);
1769 $oSrcFolder = Folder::get($iFolderID); 1788 $oSrcFolder = Folder::get($iFolderID);
1770 $oUser =& User::get($this->userID); 1789 $oUser =& User::get($this->userID);
@@ -1772,36 +1791,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1772,36 +1791,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1772 $source_path = $options["path"]; 1791 $source_path = $options["path"];
1773 $dest_path = urldecode($options["dest"]); 1792 $dest_path = urldecode($options["dest"]);
1774 1793
1775 - // Is this a rename?  
1776 - if (dirname($source_path) == dirname($dest_path)) {  
1777 - // This is a rename  
1778 - //if ($options['overwrite'] != 'T') {  
1779 - // $this->ktwebdavLog("This is a Rename. Overwrite needs to be TRUE.", 'info', true);  
1780 - // return "412 Precondition Failed - This is a Rename. Overwrite needs to be TRUE.";  
1781 - //}  
1782 - $this->ktwebdavLog("Got an oDocument of " . print_r($oDocument, true), 'info', true);  
1783 - $this->ktwebdavLog("Got a new name of " . basename($dest_path), 'info', true);  
1784 -  
1785 - // Check if the user has permissions to write this document  
1786 - $oPerm =& KTPermission::getByName('ktcore.permissions.write');  
1787 - $oUser =& User::get($this->userID);  
1788 - if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDocument)) {  
1789 - return "403 Forbidden - User does not have sufficient permissions";  
1790 - }  
1791 - $res = KTDocumentUtil::rename($oDocument, basename($dest_path), $oUser);  
1792 - if (PEAR::isError($res) || is_null($res) || ($res === false)) {  
1793 - return "404 Not Found - " . $res->getMessage();  
1794 - } else {  
1795 - $this->ktwebdavLog("201 Created", 'info', true);  
1796 - return "201 Created";  
1797 - }  
1798 -  
1799 - }  
1800 - 1794 + /* ** Get the source folder object.
  1795 + If the destination document is null, then the destination is a folder, continue.
  1796 + If the destination document returns an id, then the document exists. Check overwrite.
  1797 + If overwrite is true, then check permissions and delete the document, continue.
  1798 + If the destination document is false, then continue. ** */
1801 list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path); 1799 list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
1802 1800
1803 if (is_null($iDestDoc)) { 1801 if (is_null($iDestDoc)) {
1804 // the dest is a folder 1802 // the dest is a folder
  1803 + $this->ktwebdavLog("Destination is a folder.", 'info', true);
1805 } else if ($iDestDoc !== false) { 1804 } else if ($iDestDoc !== false) {
1806 // Document exists 1805 // Document exists
1807 $this->ktwebdavLog("Destination Document exists.", 'info', true); 1806 $this->ktwebdavLog("Destination Document exists.", 'info', true);
@@ -1822,6 +1821,39 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1822,6 +1821,39 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1822 $new = false; 1821 $new = false;
1823 } 1822 }
1824 1823
  1824 + /* ** Check if the source and destination directories are the same and the destination is not a folder.
  1825 + Then action is probably a rename.
  1826 + Check if user has permission to write to the document and folder.
  1827 + Rename the document. ** */
  1828 + if ((dirname($source_path) == dirname($dest_path)) && !is_null($iDestDoc)) {
  1829 + // This is a rename
  1830 + $this->ktwebdavLog("This is a rename.", 'info', true);
  1831 + $this->ktwebdavLog("Got an oDocument of " . print_r($oDocument, true), 'info', true);
  1832 + $this->ktwebdavLog("Got a new name of " . basename($dest_path), 'info', true);
  1833 +
  1834 + // Check if the user has permissions to write this document
  1835 + $oPerm =& KTPermission::getByName('ktcore.permissions.write');
  1836 + $oUser =& User::get($this->userID);
  1837 + if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDocument)) {
  1838 + return "403 Forbidden - User does not have sufficient permissions";
  1839 + }
  1840 +
  1841 + // Perform rename
  1842 + $res = KTDocumentUtil::rename($oDocument, basename($dest_path), $oUser);
  1843 + if (PEAR::isError($res) || is_null($res) || ($res === false)) {
  1844 + return "404 Not Found - " . $res->getMessage();
  1845 + } else if($new) {
  1846 + $this->ktwebdavLog("201 Created", 'info', true);
  1847 + return "201 Created";
  1848 + }else {
  1849 + $this->ktwebdavLog("204 No Content", 'info', true);
  1850 + return "204 No Content";
  1851 + }
  1852 + }
  1853 +
  1854 + /* ** Get the destination folder object and the source document object.
  1855 + Check if user has permission to write to the document and folder.
  1856 + Move the document. ** */
1825 $oDestFolder = Folder::get($iDestFolder); 1857 $oDestFolder = Folder::get($iDestFolder);
1826 $this->ktwebdavLog("Got a destination folder of " . print_r($oDestFolder, true), 'info', true); 1858 $this->ktwebdavLog("Got a destination folder of " . print_r($oDestFolder, true), 'info', true);
1827 1859
@@ -1832,57 +1864,20 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1832,57 +1864,20 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1832 return "403 Forbidden - User does not have sufficient permissions"; 1864 return "403 Forbidden - User does not have sufficient permissions";
1833 } 1865 }
1834 1866
1835 - $oOriginalFolder = $oSrcFolder;  
1836 - $iOriginalFolderPermissionObjectId = $oOriginalFolder->getPermissionObjectId();  
1837 - $iDocumentPermissionObjectId = $oDocument->getPermissionObjectId(); 1867 + $reason = (isset($_SERVER['HTTP_REASON']) && !empty($_SERVER['HTTP_REASON'])) ? $_SERVER['HTTP_REASON'] : "KTWebDAV Move.";
1838 1868
1839 - if ($iDocumentPermissionObjectId === $iOriginalFolderPermissionObjectId) {  
1840 - $oDocument->setPermissionObjectId($oDestFolder->getPermissionObjectId());  
1841 - } 1869 + $res = KTDocumentUtil::move($oDocument, $oDestFolder, $oUser, $reason);
1842 1870
1843 - //put the document in the new folder  
1844 - $oDocument->setFolderID($oDestFolder->getId());  
1845 - if (!$oDocument->update(true)) {  
1846 - return "502 Bad Gateway - Document update failed.";  
1847 - }  
1848 -  
1849 - //move the document on the file system  
1850 - $oStorage =& KTStorageManagerUtil::getSingleton();  
1851 - if (!$oStorage->moveDocument($oDocument, $oSrcFolder, $oDestFolder)) {  
1852 - $oDocument->setFolderID($oSrcDocumentFolder->getId());  
1853 - $oDocument->update(true);  
1854 - return "502 Bad Gateway";  
1855 - }  
1856 -  
1857 - $sMoveMessage = sprintf("Moved from %s/%s to %s/%s: %s",  
1858 - $oSrcFolder->getFullPath(),  
1859 - $oSrcFolder->getName(),  
1860 - $oDestFolder->getFullPath(),  
1861 - $oDestFolder->getName(),  
1862 - $_SERVER['HTTP_REASON']);  
1863 -  
1864 - // create the document transaction record  
1865 - $oDocumentTransaction = & new DocumentTransaction($oDocument, $sMoveMessage, 'ktcore.transactions.move');  
1866 - $oDocumentTransaction->create();  
1867 -  
1868 - $oKTTriggerRegistry = KTTriggerRegistry::getSingleton();  
1869 - $aTriggers = $oKTTriggerRegistry->getTriggers('moveDocument', 'postValidate');  
1870 - foreach ($aTriggers as $aTrigger) {  
1871 - $sTrigger = $aTrigger[0];  
1872 - $oTrigger = new $sTrigger;  
1873 - $aInfo = array(  
1874 - "document" => $oDocument,  
1875 - "old_folder" => $oSrcFolder,  
1876 - "new_folder" => $oDestFolder,  
1877 - );  
1878 - $oTrigger->setInfo($aInfo);  
1879 - $ret = $oTrigger->postValidate();  
1880 - // FIXME: handle trigger subfailures. 1871 + if(PEAR::isError($res)){
  1872 + $this->ktwebdavLog("Move on document failed: ".$res->getMessage(), 'info', true);
  1873 + return "500 Internal Server Error - Move on document failed.";
1881 } 1874 }
1882 1875
1883 if ($new) { 1876 if ($new) {
  1877 + $this->ktwebdavLog("201 Created", 'info', true);
1884 return "201 Created"; 1878 return "201 Created";
1885 } else { 1879 } else {
  1880 + $this->ktwebdavLog("204 No Content", 'info', true);
1886 return "204 No Content"; 1881 return "204 No Content";
1887 } 1882 }
1888 } 1883 }
@@ -1897,11 +1892,13 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1897,11 +1892,13 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1897 */ 1892 */
1898 function _MOVEFolder($options, $iFolderID) { 1893 function _MOVEFolder($options, $iFolderID) {
1899 1894
  1895 + /* ** Ensure that the destination path exists ** */
1900 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"])); 1896 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
1901 $this->ktwebdavLog("Entering _MOVEFolder. options are " . print_r($options, true), 'info', true); 1897 $this->ktwebdavLog("Entering _MOVEFolder. options are " . print_r($options, true), 'info', true);
1902 1898
  1899 + /* ** RFC 2518 Section 8.9.2. A folder move must have a depth of 'infinity'.
  1900 + Check the requested depth. If depth is set to '0' or '1' return a 400 error. ** */
1903 if ($options["depth"] != "infinity") { 1901 if ($options["depth"] != "infinity") {
1904 - // RFC 2518 Section 9.2, last paragraph  
1905 $this->ktwebdavLog("400 Bad request", 'info', true); 1902 $this->ktwebdavLog("400 Bad request", 'info', true);
1906 return "400 Bad request - depth must be 'inifinity'."; 1903 return "400 Bad request - depth must be 'inifinity'.";
1907 } 1904 }
@@ -1920,23 +1917,75 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1920,23 +1917,75 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1920 1917
1921 global $default; 1918 global $default;
1922 1919
  1920 + /* ** Get the relevant paths.
  1921 + Check whether the destination path refers to a folder / document. ** */
1923 $source_path = $options["path"]; 1922 $source_path = $options["path"];
1924 $dest_path = urldecode($options["dest"]); 1923 $dest_path = urldecode($options["dest"]);
  1924 + list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
1925 1925
  1926 + /* ** Get the source folder objects.
  1927 + If the destination document is null, then the destination is an existing folder. Check overwrite.
  1928 + If overwrite is true, then check permissions and delete the folder, continue.
  1929 + If the destination document returns an id, then the destination is a document, check overwrite.
  1930 + If overwrite is true, then check permissions and delete the document, continue.
  1931 + If the destination document is false, then continue. ** */
1926 $oSrcFolder = Folder::get($iFolderID); 1932 $oSrcFolder = Folder::get($iFolderID);
  1933 + $oDestFolder = Folder::get($iDestFolder);
1927 1934
1928 - list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path); 1935 + $new = true;
  1936 + if (is_null($iDestDoc)) {
  1937 + // Folder exists
  1938 + $this->ktwebdavLog("Destination Folder exists.", 'info', true);
  1939 + $oReplaceFolder = $oDestFolder;
  1940 + if ($options['overwrite'] != 'T') {
  1941 + $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true);
  1942 + return "412 Precondition Failed - Destination Folder exists. Overwrite needs to be TRUE.";
  1943 + }
  1944 + $this->ktwebdavLog("Overwrite is TRUE, deleting Destination Folder.", 'info', true);
1929 1945
1930 - $oDestFolder = Folder::get($iDestFolder); 1946 + // Check if the user has permissions to delete this folder
  1947 + $oPerm =& KTPermission::getByName('ktcore.permissions.delete');
  1948 + $oUser =& User::get($this->userID);
1931 1949
1932 - // Is this a rename?  
1933 - if (dirname($source_path) == dirname($dest_path)) {  
1934 - // This is a rename  
1935 - //if ($options['overwrite'] != 'T') {  
1936 - // $this->ktwebdavLog("This is a Rename. Overwrite needs to be TRUE.", 'info', true);  
1937 - // return "412 Precondition Failed - This is a Rename. Overwrite needs to be TRUE.";  
1938 - //} 1950 + if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceFolder)) {
  1951 + return "403 Forbidden - User does not have sufficient permissions";
  1952 + }
  1953 +
  1954 + KTFolderUtil::delete($oReplaceFolder, $oUser, 'KTWebDAV move overwrites target.');
  1955 +
  1956 + // Destination folder has been replaced so we need to get the parent folder object
  1957 + list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
  1958 + $oDestFolder = Folder::get($iDestFolder);
  1959 +
  1960 + $new = false;
  1961 + } else if ($iDestDoc !== false) {
  1962 + // Destination is a document
  1963 + $this->ktwebdavLog("Destination is a document.", 'info', true);
  1964 + $oReplaceDoc = Document::get($iDestDoc);
  1965 + if ($options['overwrite'] != 'T') {
  1966 + $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true);
  1967 + return "412 Precondition Failed - Destination Folder is a document. Overwrite needs to be TRUE.";
  1968 + }
  1969 + $this->ktwebdavLog("Overwrite is TRUE, deleting Destination Document.", 'info', true);
  1970 +
  1971 + // Check if the user has permissions to delete this document
  1972 + $oPerm =& KTPermission::getByName('ktcore.permissions.delete');
  1973 + $oUser =& User::get($this->userID);
  1974 +
  1975 + if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceDoc)) {
  1976 + return "403 Forbidden - User does not have sufficient permissions";
  1977 + }
  1978 + KTDocumentUtil::delete($oReplaceDoc, 'KTWebDAV move overwrites target.');
  1979 + $new = false;
  1980 + }
1939 1981
  1982 + /* ** Check if the source and destination directories are the same and the destination is not an existing folder.
  1983 + Then action is probably a rename.
  1984 + Check if user has permission to write to the folder.
  1985 + Rename the document. ** */
  1986 + if (dirname($source_path) == dirname($dest_path) && !is_null($iDestDoc)) {
  1987 + // This is a rename
  1988 + $this->ktwebdavLog("Rename collection.", 'info', true);
1940 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true); 1989 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
1941 $this->ktwebdavLog("Got an new name of " . basename($dest_path), 'info', true); 1990 $this->ktwebdavLog("Got an new name of " . basename($dest_path), 'info', true);
1942 1991
@@ -1952,36 +2001,22 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1952,36 +2001,22 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1952 if (PEAR::isError($res) || is_null($res) || ($res === false)) { 2001 if (PEAR::isError($res) || is_null($res) || ($res === false)) {
1953 return "404 Not Found - " . $res->getMessage(); 2002 return "404 Not Found - " . $res->getMessage();
1954 } else { 2003 } else {
1955 - $this->ktwebdavLog("201 Created", 'info', true);  
1956 - return "201 Created";  
1957 - }  
1958 -  
1959 - }  
1960 -  
1961 - if (is_null($iDestDoc)) {  
1962 - // the dest is a folder  
1963 - } else if ($iDestDoc !== false) {  
1964 - // Folder exists  
1965 - $this->ktwebdavLog("Destination Folder exists.", 'info', true);  
1966 - $oReplaceFolder = Folder::get($iDestDoc);  
1967 - if ($options['overwrite'] != 'T') {  
1968 - $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true);  
1969 - return "412 Precondition Failed - Destination Folder exists. Overwrite needs to be TRUE."; 2004 + if($new){
  2005 + $this->ktwebdavLog("201 Created", 'info', true);
  2006 + return "201 Created";
  2007 + }else{
  2008 + $this->ktwebdavLog("204 No Content", 'info', true);
  2009 + return "204 No Content";
  2010 + }
1970 } 2011 }
1971 - $this->ktwebdavLog("Overwrite is TRUE, deleting Destination Folder.", 'info', true);  
1972 2012
1973 - // Check if the user has permissions to delete this folder  
1974 - $oPerm =& KTPermission::getByName('ktcore.permissions.delete');  
1975 - $oUser =& User::get($this->userID);  
1976 - if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceFolder)) {  
1977 - return "403 Forbidden - User does not have sufficient permissions";  
1978 - }  
1979 - KTFolderUtil::delete($oReplaceFolder, 'KTWebDAV move overwrites target.');  
1980 - $new = false;  
1981 } 2013 }
1982 2014
1983 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php'); 2015 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
1984 2016
  2017 + /* ** Get the destination folder object and the source document object.
  2018 + Check if user has permission to write to the folder.
  2019 + Move the folder. ** */
1985 $oUser =& User::get($this->userID); 2020 $oUser =& User::get($this->userID);
1986 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true); 2021 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
1987 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true); 2022 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true);
@@ -1993,18 +2028,29 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -1993,18 +2028,29 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1993 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) { 2028 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
1994 return "403 Forbidden - User does not have sufficient permissions"; 2029 return "403 Forbidden - User does not have sufficient permissions";
1995 } 2030 }
1996 - KTFolderUtil::move($oSrcFolder, $oDestFolder, $oUser);  
1997 2031
1998 - $this->ktwebdavLog("201 Created", 'info', true);  
1999 - return "201 Created"; 2032 + $res = KTFolderUtil::move($oSrcFolder, $oDestFolder, $oUser);
  2033 +
  2034 + if(PEAR::isError($res)){
  2035 + $this->ktwebdavLog("Move on folder failed: ".$res->getMessage(), 'info', true);
  2036 + return "500 Internal Server Error - Move on folder failed.";
  2037 + }
2000 2038
  2039 + if($new){
  2040 + $this->ktwebdavLog("201 Created", 'info', true);
  2041 + return "201 Created";
  2042 + }else{
  2043 + $this->ktwebdavLog("204 No Content", 'info', true);
  2044 + return "204 No Content";
  2045 + }
2001 } 2046 }
2002 2047
2003 /** 2048 /**
2004 * COPY method handler 2049 * COPY method handler
  2050 + * Method checks if the source path refers to a document / folder then calls the appropriate method handler.
2005 * 2051 *
2006 - * @param array parameter passing array  
2007 - * @param string delete source flag 2052 + * @param $options array parameter passing array
  2053 + * @param $del string delete source flag
2008 * @return string HTTP status code or false 2054 * @return string HTTP status code or false
2009 */ 2055 */
2010 function COPY($options, $del = false) 2056 function COPY($options, $del = false)
@@ -2012,6 +2058,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2012,6 +2058,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2012 $this->ktwebdavLog("Entering COPY. options are " . print_r($options, true), 'info', true); 2058 $this->ktwebdavLog("Entering COPY. options are " . print_r($options, true), 'info', true);
2013 $this->ktwebdavLog("del is: " . $del, 'info', true); 2059 $this->ktwebdavLog("del is: " . $del, 'info', true);
2014 2060
  2061 + /* ** Check that writing to the server is allowed * **/
2015 if ($this->checkSafeMode()) { 2062 if ($this->checkSafeMode()) {
2016 2063
2017 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet 2064 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
@@ -2025,6 +2072,10 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2025,6 +2072,10 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2025 return "502 bad gateway - No copying to different WebDAV Servers yet"; 2072 return "502 bad gateway - No copying to different WebDAV Servers yet";
2026 } 2073 }
2027 */ 2074 */
  2075 +
  2076 + /* ** Get the path to the document/folder to be copied.
  2077 + Call function to check if the path refers to a document or a folder.
  2078 + Return 404 error if the path is invalid. ** */
2028 $source_path = $options["path"]; 2079 $source_path = $options["path"];
2029 $this->ktwebdavLog("SourcePath is: " . $source_path, 'info', true); 2080 $this->ktwebdavLog("SourcePath is: " . $source_path, 'info', true);
2030 $source_res = $this->_folderOrDocument($source_path); 2081 $source_res = $this->_folderOrDocument($source_path);
@@ -2033,13 +2084,19 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2033,13 +2084,19 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2033 return "404 Not found - The document could not be found."; 2084 return "404 Not found - The document could not be found.";
2034 } 2085 }
2035 2086
  2087 + /* ** Get the returned parent folder id and document/folder id.
  2088 + If the parent folder id is false, return 404 error.
  2089 + If the document id is either false or null, then the source is a folder.
  2090 + If the document id exists then the source is a document.
  2091 + If the source is a folder then call _COPYFolder.
  2092 + If the source is a document then check if its checked out and call _COPYDocument. ** */
2036 list($iFolderID, $iDocumentID) = $source_res; 2093 list($iFolderID, $iDocumentID) = $source_res;
2037 - if ($iDocumentID === false) { 2094 + if ($iFolderID === false && ($iDocumentID === false || is_null($iDocumentID))) {
2038 $this->ktwebdavLog("404 Not found - The folder could not be found.", 'info', true); 2095 $this->ktwebdavLog("404 Not found - The folder could not be found.", 'info', true);
2039 return "404 Not found - The folder could not be found."; 2096 return "404 Not found - The folder could not be found.";
2040 } 2097 }
2041 2098
2042 - if (is_null($iDocumentID)) { 2099 + if (is_null($iDocumentID) || $iDocumentID === false) {
2043 // Source is a folder 2100 // Source is a folder
2044 $this->ktwebdavLog("Source is a Folder.", 'info', true); 2101 $this->ktwebdavLog("Source is a Folder.", 'info', true);
2045 $copystat = $this->_COPYFolder($options, $iFolderID); 2102 $copystat = $this->_COPYFolder($options, $iFolderID);
@@ -2049,13 +2106,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2049,13 +2106,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2049 $this->ktwebdavLog("Source is a Document.", 'info', true); 2106 $this->ktwebdavLog("Source is a Document.", 'info', true);
2050 2107
2051 if ($this->canCopyMoveRenameDocument($iDocumentID)) { 2108 if ($this->canCopyMoveRenameDocument($iDocumentID)) {
2052 - $copystat = $this->_COPYDocument($options, $iFolderID, $iDocumentID, $dest_folder_id); 2109 + $copystat = $this->_COPYDocument($options, $iFolderID, $iDocumentID);
2053 } else { 2110 } else {
2054 - return "Cannot COPY document because it is checked out by another user."; 2111 + // Document is locked
  2112 + return "423 Locked - Cannot COPY document because it is checked out by another user.";
2055 } 2113 }
2056 2114
2057 } 2115 }
2058 2116
  2117 + /* ** Deprecated. If the request is a move then delete the source **
2059 // Delete the source if this is a move and the copy was ok 2118 // Delete the source if this is a move and the copy was ok
2060 if ($del && ($copystat{0} == "2")) { 2119 if ($del && ($copystat{0} == "2")) {
2061 $delstat = $this->DELETE(array("path" => $options["path"])); 2120 $delstat = $this->DELETE(array("path" => $options["path"]));
@@ -2064,6 +2123,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2064,6 +2123,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2064 return $delstat; 2123 return $delstat;
2065 } 2124 }
2066 } 2125 }
  2126 + */
2067 2127
2068 $this->ktwebdavLog("Final copystat result is: " . $copystat, 'info', true); 2128 $this->ktwebdavLog("Final copystat result is: " . $copystat, 'info', true);
2069 return $copystat; 2129 return $copystat;
@@ -2074,16 +2134,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2074,16 +2134,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2074 /** 2134 /**
2075 * COPY method helper for Documents 2135 * COPY method helper for Documents
2076 * 2136 *
2077 - * @param array parameter passing array  
2078 - * @param int Folder ID  
2079 - * @param int Document ID 2137 + * @param $options array parameter passing array
  2138 + * @param $iFolderID int Folder ID
  2139 + * @param $iDocumentID int Document ID
2080 * @return string HTTP status code or false 2140 * @return string HTTP status code or false
2081 */ 2141 */
2082 function _COPYDocument($options, $iFolderID, $iDocumentID) { 2142 function _COPYDocument($options, $iFolderID, $iDocumentID) {
2083 2143
  2144 + /* ** Ensure that the destination path exists ** */
2084 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"])); 2145 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
2085 $this->ktwebdavLog("Entering _COPYDocument. options are " . print_r($options, true), 'info', true); 2146 $this->ktwebdavLog("Entering _COPYDocument. options are " . print_r($options, true), 'info', true);
2086 2147
  2148 + /* ** Get the relevant paths. Get the basename of the destination path as the destination filename.
  2149 + Check whether the destination path refers to a folder / document. ** */
  2150 + $source_path = $options["path"];
  2151 + $dest_path = urldecode($options["dest"]);
  2152 + $sDestFileName = basename($dest_path);
  2153 +
  2154 + list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
  2155 +
  2156 + if($iDestFolder === false){
  2157 + return "409 Conflict - Destination folder does not exist.";
  2158 + }
  2159 +
  2160 + /* ** Depth must be infinity to copy a document ** */
2087 if ($options["depth"] != "infinity") { 2161 if ($options["depth"] != "infinity") {
2088 // RFC 2518 Section 9.2, last paragraph 2162 // RFC 2518 Section 9.2, last paragraph
2089 $this->ktwebdavLog("400 Bad request", 'info', true); 2163 $this->ktwebdavLog("400 Bad request", 'info', true);
@@ -2092,17 +2166,20 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2092,17 +2166,20 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2092 2166
2093 global $default; 2167 global $default;
2094 2168
2095 - $source_path = $options["path"];  
2096 - $dest_path = urldecode($options["dest"]);  
2097 - 2169 + /* ** Get the source folder object.
  2170 + If the destination document is null, then the destination is a folder, set the destination filename to empty, continue.
  2171 + If the destination document returns an id, then the document exists. Check overwrite.
  2172 + If overwrite is true, then check permissions and delete the document, continue.
  2173 + If the destination document is false, then continue. ** */
2098 $oSrcFolder = Folder::get($iFolderID); 2174 $oSrcFolder = Folder::get($iFolderID);
2099 2175
2100 - list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);  
2101 - 2176 + $new = true;
2102 if (is_null($iDestDoc)) { 2177 if (is_null($iDestDoc)) {
2103 // the dest is a folder 2178 // the dest is a folder
2104 // $this->ktwebdavLog("400 Bad request", 'info', true); 2179 // $this->ktwebdavLog("400 Bad request", 'info', true);
2105 - return "400 Bad request - Destination is a Folder"; 2180 + $this->ktwebdavLog("Destination is a folder.", 'info', true);
  2181 + $sDestFileName = '';
  2182 + //return "400 Bad request - Destination is a Folder";
2106 } else if ($iDestDoc !== false) { 2183 } else if ($iDestDoc !== false) {
2107 // Document exists 2184 // Document exists
2108 $this->ktwebdavLog("Destination Document exists.", 'info', true); 2185 $this->ktwebdavLog("Destination Document exists.", 'info', true);
@@ -2123,25 +2200,33 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2123,25 +2200,33 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2123 $new = false; 2200 $new = false;
2124 } 2201 }
2125 2202
  2203 + /* ** Get the destination folder object and the source document object.
  2204 + Check if user has permission to write to the document and folder.
  2205 + Copy the document. ** */
2126 $oDestFolder = Folder::get($iDestFolder); 2206 $oDestFolder = Folder::get($iDestFolder);
2127 $oSrcDoc = Document::get($iDocumentID); 2207 $oSrcDoc = Document::get($iDocumentID);
2128 2208
2129 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php'); 2209 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
2130 2210
2131 - $this->ktwebdavLog("Got an oSrcDoc of " . print_r($oSrcDoc, true), 'info', true);  
2132 - $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true); 2211 + $this->ktwebdavLog("Got an oSrcDoc of " .$oSrcDoc->getName() . print_r($oSrcDoc, true), 'info', true);
  2212 + $this->ktwebdavLog("Got an oDestFolder of " .$oDestFolder->getName() . print_r($oDestFolder, true), 'info', true);
2133 2213
2134 // Check if the user has permissions to write in this folder 2214 // Check if the user has permissions to write in this folder
2135 $oPerm =& KTPermission::getByName('ktcore.permissions.write'); 2215 $oPerm =& KTPermission::getByName('ktcore.permissions.write');
2136 $oUser =& User::get($this->userID); 2216 $oUser =& User::get($this->userID);
2137 - if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oSrcDoc)) { 2217 + if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
2138 return "403 Forbidden - User does not have sufficient permissions"; 2218 return "403 Forbidden - User does not have sufficient permissions";
2139 } 2219 }
2140 - KTDocumentUtil::copy($oSrcDoc, $oDestFolder, $_SERVER['HTTP_REASON']);  
2141 2220
2142 - // FIXME: Do failure checking here 2221 + $reason = (isset($_SERVER['HTTP_REASON']) && !empty($_SERVER['HTTP_REASON'])) ? $_SERVER['HTTP_REASON'] : "KTWebDAV Copy.";
  2222 +
  2223 + $oDesDoc = KTDocumentUtil::copy($oSrcDoc, $oDestFolder, $reason, $sDestFileName);
  2224 +
  2225 + if(PEAR::isError($oDesDoc)){
  2226 + $this->ktwebdavLog("Copy on document failed: ".$oDesDoc->getMessage(), 'info', true);
  2227 + return "500 Internal Server Error - Copy on document failed.";
  2228 + }
2143 2229
2144 - $new = false;  
2145 if ($new) { 2230 if ($new) {
2146 $this->ktwebdavLog("201 Created", 'info', true); 2231 $this->ktwebdavLog("201 Created", 'info', true);
2147 return "201 Created"; 2232 return "201 Created";
@@ -2160,37 +2245,52 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2160,37 +2245,52 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2160 */ 2245 */
2161 function _COPYFolder($options, $iFolderID) { 2246 function _COPYFolder($options, $iFolderID) {
2162 2247
  2248 + /* ** Ensure that the destination path exists ** */
2163 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"])); 2249 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
2164 $this->ktwebdavLog("Entering _COPYFolder. options are " . print_r($options, true), 'info', true); 2250 $this->ktwebdavLog("Entering _COPYFolder. options are " . print_r($options, true), 'info', true);
2165 2251
  2252 + /* ** RFC 2518 Section 8.8.3. DAV compliant servers must support depth headers of '0' and 'infinity'.
  2253 + Check the requested depth. If depth is set to '0', set copyall to false. A depth of 0 indicates
  2254 + that the folder is copied without any children. If depth is set to '1', return a 400 error. ** */
  2255 + $copyAll = true;
2166 if ($options["depth"] != "infinity") { 2256 if ($options["depth"] != "infinity") {
2167 - // RFC 2518 Section 9.2, last paragraph  
2168 - $this->ktwebdavLog("400 Bad request", 'info', true);  
2169 - return "400 Bad request - Depth must be 'infinity'."; 2257 + if($options['depth'] == '0'){
  2258 + $copyAll = false;
  2259 + $this->ktwebdavLog("Depth is 0. Copy only the base folder.", 'info', true);
  2260 + }else{
  2261 + $this->ktwebdavLog("400 Bad request. Depth must be infinity or 0.", 'info', true);
  2262 + return "400 Bad request - Depth must be 'infinity' or '0'.";
  2263 + }
2170 } 2264 }
2171 2265
2172 global $default; 2266 global $default;
2173 2267
2174 $new = true; 2268 $new = true;
2175 2269
  2270 + /* ** Get the relevant paths. Get the basename of the destination path as the destination path name.
  2271 + Check whether the destination path refers to a folder / document. ** */
2176 $source_path = $options["path"]; 2272 $source_path = $options["path"];
2177 $dest_path = urldecode($options["dest"]); 2273 $dest_path = urldecode($options["dest"]);
2178 -  
2179 - $oSrcFolder = Folder::get($iFolderID); 2274 + $sDestPathName = basename($dest_path);
2180 2275
2181 list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path); 2276 list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
2182 2277
  2278 + /* ** Get the source and destination folder objects.
  2279 + If the destination document is null, then the destination is an existing folder. Check overwrite.
  2280 + If overwrite is true, then check permissions and delete the folder, continue.
  2281 + If the destination document returns an id, then the destination is a document, return 409 error.
  2282 + If the destination document is false, then continue. ** */
  2283 + $oSrcFolder = Folder::get($iFolderID);
2183 $oDestFolder = Folder::get($iDestFolder); 2284 $oDestFolder = Folder::get($iDestFolder);
2184 2285
2185 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php'); 2286 include_once(KT_LIB_DIR . '/foldermanagement/folderutil.inc.php');
2186 2287
2187 - if (is_null($iDestDoc)) {  
2188 - // the dest is a folder  
2189 - $this->ktwebdavLog("The Destination is a Folder.", 'info', true);  
2190 - } else if ($iDestDoc !== false) {  
2191 - // Folder exists 2288 + if(is_null($iDestDoc)) {
  2289 + // Destination is a folder and exists
  2290 + //$sDestPathName = '';
2192 $this->ktwebdavLog("Destination Folder exists.", 'info', true); 2291 $this->ktwebdavLog("Destination Folder exists.", 'info', true);
2193 - $oReplaceFolder = Folder::get($iDestDoc); 2292 +
  2293 + $oReplaceFolder = $oDestFolder;
2194 if ($options['overwrite'] != 'T') { 2294 if ($options['overwrite'] != 'T') {
2195 $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true); 2295 $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true);
2196 return "412 Precondition Failed - Destination Folder exists. Overwrite needs to be TRUE."; 2296 return "412 Precondition Failed - Destination Folder exists. Overwrite needs to be TRUE.";
@@ -2203,10 +2303,21 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2203,10 +2303,21 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2203 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceFolder)) { 2303 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceFolder)) {
2204 return "403 Forbidden - User does not have sufficient permissions"; 2304 return "403 Forbidden - User does not have sufficient permissions";
2205 } 2305 }
2206 - KTFolderUtil::delete($oReplaceFolder, 'KTWebDAV move overwrites target.'); 2306 + KTFolderUtil::delete($oReplaceFolder, $oUser, 'KTWebDAV move overwrites target.');
  2307 +
  2308 + // Destination folder has been deleted - get new object of destination parent folder
  2309 + list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
  2310 + $oDestFolder = Folder::get($iDestFolder);
  2311 +
2207 $new = false; 2312 $new = false;
  2313 + } else if ($iDestDoc !== false) {
  2314 + // Destination is a document
  2315 + return "409 Conflict - Can't write a collection to a document";
2208 } 2316 }
2209 2317
  2318 + /* ** Get the destination folder object and the source document object.
  2319 + Check if user has permission to write to the folder.
  2320 + Copy the document. Pass parameters for the destination folder name and the depth of copy. ** */
2210 $oUser =& User::get($this->userID); 2321 $oUser =& User::get($this->userID);
2211 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true); 2322 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
2212 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true); 2323 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true);
@@ -2218,7 +2329,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server @@ -2218,7 +2329,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2218 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) { 2329 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
2219 return "403 Forbidden - User does not have sufficient permissions"; 2330 return "403 Forbidden - User does not have sufficient permissions";
2220 } 2331 }
2221 - KTFolderUtil::copy($oSrcFolder, $oDestFolder, $oUser, 'KTWebDAV Copy.'); 2332 +
  2333 + $reason = (isset($_SERVER['HTTP_REASON']) && !empty($_SERVER['HTTP_REASON'])) ? $_SERVER['HTTP_REASON'] : "KTWebDAV Copy.";
  2334 +
  2335 + $res = KTFolderUtil::copy($oSrcFolder, $oDestFolder, $oUser, $reason, $sDestPathName, $copyAll);
  2336 +
  2337 + if(PEAR::isError($res)){
  2338 + $this->ktwebdavLog("Copy on folder failed: ".$res->getMessage(), 'info', true);
  2339 + return "500 Internal Server Error - Copy on folder failed.";
  2340 + }
2222 2341
2223 if ($new) { 2342 if ($new) {
2224 $this->ktwebdavLog("201 Created", 'info', true); 2343 $this->ktwebdavLog("201 Created", 'info', true);
lib/documentmanagement/documentutil.inc.php
@@ -638,14 +638,14 @@ class KTDocumentUtil { @@ -638,14 +638,14 @@ class KTDocumentUtil {
638 return $oDocument; 638 return $oDocument;
639 } 639 }
640 // }}} 640 // }}}
641 - 641 +
642 function generateNewDocumentFilename($sDocFilename){ 642 function generateNewDocumentFilename($sDocFilename){
643 if(preg_match("/\([0-9]+\)(\.[^\.]+){1,}$/", $sDocFilename)){ 643 if(preg_match("/\([0-9]+\)(\.[^\.]+){1,}$/", $sDocFilename)){
644 preg_match("/\([0-9]+\)\./", $sDocFilename, $matches); 644 preg_match("/\([0-9]+\)\./", $sDocFilename, $matches);
645 $new_one = substr($matches[0], 1); 645 $new_one = substr($matches[0], 1);
646 $new_two = explode(')', $new_one); 646 $new_two = explode(')', $new_one);
647 $new = $new_two[0]+1; 647 $new = $new_two[0]+1;
648 - 648 +
649 $pattern[0] = '/\([0-9]+\)\./'; 649 $pattern[0] = '/\([0-9]+\)\./';
650 $replacement[0] = ' ('.$new.').'; 650 $replacement[0] = ' ('.$new.').';
651 $sFilename = preg_replace($pattern, $replacement, $sDocFilename); 651 $sFilename = preg_replace($pattern, $replacement, $sDocFilename);
@@ -657,27 +657,27 @@ class KTDocumentUtil { @@ -657,27 +657,27 @@ class KTDocumentUtil {
657 } 657 }
658 $sFilename = $prefix.$suffix; 658 $sFilename = $prefix.$suffix;
659 } 659 }
660 - 660 +
661 return $sFilename; 661 return $sFilename;
662 } 662 }
663 -  
664 - function generateNewDocumentName($sDocName){ 663 +
  664 + function generateNewDocumentName($sDocName){
665 if(preg_match("/\([0-9]+\)$/", $sDocName)){ 665 if(preg_match("/\([0-9]+\)$/", $sDocName)){
666 preg_match("/\([0-9]+\)$/", $sDocName, $matches); 666 preg_match("/\([0-9]+\)$/", $sDocName, $matches);
667 $new_one = substr($matches[0], 1); 667 $new_one = substr($matches[0], 1);
668 $new_two = explode(')', $new_one); 668 $new_two = explode(')', $new_one);
669 $new = $new_two[0]+1; 669 $new = $new_two[0]+1;
670 - 670 +
671 $pattern[0] = '/\([0-9]+\)$/'; 671 $pattern[0] = '/\([0-9]+\)$/';
672 $replacement[0] = '('.$new.')'; 672 $replacement[0] = '('.$new.')';
673 $sName = preg_replace($pattern, $replacement, $sDocName); 673 $sName = preg_replace($pattern, $replacement, $sDocName);
674 }else{ 674 }else{
675 $sName = $sDocName.' (2)'; 675 $sName = $sDocName.' (2)';
676 } 676 }
677 - 677 +
678 return $sName; 678 return $sName;
679 } 679 }
680 - 680 +
681 // {{{ fileExists 681 // {{{ fileExists
682 function fileExists($oFolder, $sFilename) { 682 function fileExists($oFolder, $sFilename) {
683 return Document::fileExists($sFilename, $oFolder->getID()); 683 return Document::fileExists($sFilename, $oFolder->getID());
@@ -939,7 +939,7 @@ class KTDocumentUtil { @@ -939,7 +939,7 @@ class KTDocumentUtil {
939 } 939 }
940 940
941 941
942 - function copy($oDocument, $oDestinationFolder, $sReason = null) { 942 + function copy($oDocument, $oDestinationFolder, $sReason = null, $sDestinationDocName = null) {
943 // 1. generate a new triad of content, metadata and core objects. 943 // 1. generate a new triad of content, metadata and core objects.
944 // 2. update the storage path. 944 // 2. update the storage path.
945 //print '--------------------------------- BEFORE'; 945 //print '--------------------------------- BEFORE';
@@ -958,23 +958,36 @@ class KTDocumentUtil { @@ -958,23 +958,36 @@ class KTDocumentUtil {
958 // we still have a bogus md_version, but integrity holds, so fix it now. 958 // we still have a bogus md_version, but integrity holds, so fix it now.
959 $oCore = KTDocumentCore::get($id); 959 $oCore = KTDocumentCore::get($id);
960 960
  961 + // Get the metadata version for the source document
961 $sTable = KTUtil::getTableName('document_metadata_version'); 962 $sTable = KTUtil::getTableName('document_metadata_version');
962 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?'; 963 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?';
963 $aParams = array($oDocument->getMetadataVersionId()); 964 $aParams = array($oDocument->getMetadataVersionId());
964 $aMDRow = DBUtil::getOneResult(array($sQuery, $aParams)); 965 $aMDRow = DBUtil::getOneResult(array($sQuery, $aParams));
965 unset($aMDRow['id']); 966 unset($aMDRow['id']);
  967 +
  968 + // Copy the source metadata into the destination document
966 $aMDRow['document_id'] = $oCore->getId(); 969 $aMDRow['document_id'] = $oCore->getId();
  970 + if(!empty($sDestinationDocName)){
  971 + $aMDRow['name'] = $sDestinationDocName;
  972 + $aMDRow['description'] = $sDestinationDocName;
  973 + }
967 $id = DBUtil::autoInsert($sTable, $aMDRow); 974 $id = DBUtil::autoInsert($sTable, $aMDRow);
968 if (PEAR::isError($id)) { return $id; } 975 if (PEAR::isError($id)) { return $id; }
969 $oCore->setMetadataVersionId($id); 976 $oCore->setMetadataVersionId($id);
970 $oMDV = KTDocumentMetadataVersion::get($id); 977 $oMDV = KTDocumentMetadataVersion::get($id);
971 978
  979 + // Get the content version for the source document
972 $sTable = KTUtil::getTableName('document_content_version'); 980 $sTable = KTUtil::getTableName('document_content_version');
973 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?'; 981 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?';
974 $aParams = array($oDocument->_oDocumentContentVersion->getId()); 982 $aParams = array($oDocument->_oDocumentContentVersion->getId());
975 $aContentRow = DBUtil::getOneResult(array($sQuery, $aParams)); 983 $aContentRow = DBUtil::getOneResult(array($sQuery, $aParams));
976 unset($aContentRow['id']); 984 unset($aContentRow['id']);
  985 +
  986 + // Copy the source content into the destination document
977 $aContentRow['document_id'] = $oCore->getId(); 987 $aContentRow['document_id'] = $oCore->getId();
  988 + if(!empty($sDestinationDocName)){
  989 + $aContentRow['filename'] = $sDestinationDocName;
  990 + }
978 $id = DBUtil::autoInsert($sTable, $aContentRow); 991 $id = DBUtil::autoInsert($sTable, $aContentRow);
979 if (PEAR::isError($id)) { return $id; } 992 if (PEAR::isError($id)) { return $id; }
980 $oMDV->setContentVersionId($id); 993 $oMDV->setContentVersionId($id);
@@ -996,6 +1009,7 @@ class KTDocumentUtil { @@ -996,6 +1009,7 @@ class KTDocumentUtil {
996 $res = KTDocumentUtil::copyMetadata($oNewDocument, $oDocument->getMetadataVersionId()); 1009 $res = KTDocumentUtil::copyMetadata($oNewDocument, $oDocument->getMetadataVersionId());
997 if (PEAR::isError($res)) { return $res; } 1010 if (PEAR::isError($res)) { return $res; }
998 1011
  1012 + // Ensure the copied document is not checked out
999 $oNewDocument->setIsCheckedOut(false); 1013 $oNewDocument->setIsCheckedOut(false);
1000 $oNewDocument->setCheckedOutUserID(-1); 1014 $oNewDocument->setCheckedOutUserID(-1);
1001 1015
lib/foldermanagement/folderutil.inc.php
@@ -7,32 +7,32 @@ @@ -7,32 +7,32 @@
7 * KnowledgeTree Open Source Edition 7 * KnowledgeTree Open Source Edition
8 * Document Management Made Simple 8 * Document Management Made Simple
9 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited 9 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited
10 - * 10 + *
11 * This program is free software; you can redistribute it and/or modify it under 11 * This program is free software; you can redistribute it and/or modify it under
12 * the terms of the GNU General Public License version 3 as published by the 12 * the terms of the GNU General Public License version 3 as published by the
13 * Free Software Foundation. 13 * Free Software Foundation.
14 - * 14 + *
15 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details. 18 * details.
19 - * 19 + *
20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>. 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 - * 22 + *
23 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, 23 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
24 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. 24 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
25 - * 25 + *
26 * The interactive user interfaces in modified source and object code versions 26 * The interactive user interfaces in modified source and object code versions
27 * of this program must display Appropriate Legal Notices, as required under 27 * of this program must display Appropriate Legal Notices, as required under
28 * Section 5 of the GNU General Public License version 3. 28 * Section 5 of the GNU General Public License version 3.
29 - * 29 + *
30 * In accordance with Section 7(b) of the GNU General Public License version 3, 30 * In accordance with Section 7(b) of the GNU General Public License version 3,
31 * these Appropriate Legal Notices must retain the display of the "Powered by 31 * these Appropriate Legal Notices must retain the display of the "Powered by
32 - * KnowledgeTree" logo and retain the original copyright notice. If the display of the 32 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 33 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
34 - * must display the words "Powered by KnowledgeTree" and retain the original  
35 - * copyright notice. 34 + * must display the words "Powered by KnowledgeTree" and retain the original
  35 + * copyright notice.
36 * Contributor( s): ______________________________________ 36 * Contributor( s): ______________________________________
37 */ 37 */
38 38
@@ -414,8 +414,9 @@ class KTFolderUtil { @@ -414,8 +414,9 @@ class KTFolderUtil {
414 return true; 414 return true;
415 } 415 }
416 416
417 - function copy($oSrcFolder, $oDestFolder, $oUser, $sReason) {  
418 - if (KTFolderUtil::exists($oDestFolder, $oSrcFolder->getName())) { 417 + function copy($oSrcFolder, $oDestFolder, $oUser, $sReason, $sDestFolderName = NULL, $copyAll = true) {
  418 + $sDestFolderName = (empty($sDestFolderName)) ? $oSrcFolder->getName() : $sDestFolderName;
  419 + if (KTFolderUtil::exists($oDestFolder, $sDestFolderName)) {
419 return PEAR::raiseError(_kt("Folder with the same name already exists in the new parent folder")); 420 return PEAR::raiseError(_kt("Folder with the same name already exists in the new parent folder"));
420 } 421 }
421 // 422 //
@@ -437,7 +438,7 @@ class KTFolderUtil { @@ -437,7 +438,7 @@ class KTFolderUtil {
437 438
438 DBUtil::startTransaction(); 439 DBUtil::startTransaction();
439 440
440 - while (!empty($aRemainingFolders)) { 441 + while (!empty($aRemainingFolders) && $copyAll) {
441 $iFolderId = array_pop($aRemainingFolders); 442 $iFolderId = array_pop($aRemainingFolders);
442 $oFolder = Folder::get($iFolderId); 443 $oFolder = Folder::get($iFolderId);
443 if (PEAR::isError($oFolder) || ($oFolder == false)) { 444 if (PEAR::isError($oFolder) || ($oFolder == false)) {
@@ -487,15 +488,18 @@ class KTFolderUtil { @@ -487,15 +488,18 @@ class KTFolderUtil {
487 488
488 $aFolderMap = array(); 489 $aFolderMap = array();
489 490
490 - $sTable = KTUtil::getTableName('folders'); 491 + $sTable = 'folders';
491 $sGetQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ? '; 492 $sGetQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ? ';
492 $aParams = array($oSrcFolder->getId()); 493 $aParams = array($oSrcFolder->getId());
493 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams)); 494 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams));
494 unset($aRow['id']); 495 unset($aRow['id']);
  496 +
  497 + $aRow['name'] = $sDestFolderName;
  498 + $aRow['description'] = $sDestFolderName;
495 $aRow['parent_id'] = $oDestFolder->getId(); 499 $aRow['parent_id'] = $oDestFolder->getId();
496 $aRow['parent_folder_ids'] = sprintf('%s,%s', $oDestFolder->getParentFolderIDs(), $oDestFolder->getId()); 500 $aRow['parent_folder_ids'] = sprintf('%s,%s', $oDestFolder->getParentFolderIDs(), $oDestFolder->getId());
497 $aRow['full_path'] = sprintf('%s/%s', $oDestFolder->getFullPath(), $oDestFolder->getName()); 501 $aRow['full_path'] = sprintf('%s/%s', $oDestFolder->getFullPath(), $oDestFolder->getName());
498 - 502 +
499 $id = DBUtil::autoInsert($sTable, $aRow); 503 $id = DBUtil::autoInsert($sTable, $aRow);
500 if (PEAR::isError($id)) { 504 if (PEAR::isError($id)) {
501 DBUtil::rollback(); 505 DBUtil::rollback();
@@ -506,7 +510,7 @@ class KTFolderUtil { @@ -506,7 +510,7 @@ class KTFolderUtil {
506 $aFolderMap[$sSrcFolderId]['parent_folder_ids'] = $aRow['parent_folder_ids']; 510 $aFolderMap[$sSrcFolderId]['parent_folder_ids'] = $aRow['parent_folder_ids'];
507 $aFolderMap[$sSrcFolderId]['full_path'] = $aRow['full_path']; 511 $aFolderMap[$sSrcFolderId]['full_path'] = $aRow['full_path'];
508 $aFolderMap[$sSrcFolderId]['name'] = $aRow['name']; 512 $aFolderMap[$sSrcFolderId]['name'] = $aRow['name'];
509 - 513 +
510 $oNewBaseFolder = Folder::get($id); 514 $oNewBaseFolder = Folder::get($id);
511 $res = $oStorage->createFolder($oNewBaseFolder); 515 $res = $oStorage->createFolder($oNewBaseFolder);
512 if (PEAR::isError($res)) { 516 if (PEAR::isError($res)) {
@@ -517,12 +521,13 @@ class KTFolderUtil { @@ -517,12 +521,13 @@ class KTFolderUtil {
517 $aRemainingFolders = Folder::getList(array('parent_id = ?', array($oSrcFolder->getId())), array('ids' => true)); 521 $aRemainingFolders = Folder::getList(array('parent_id = ?', array($oSrcFolder->getId())), array('ids' => true));
518 522
519 523
520 - while (!empty($aRemainingFolders)) { 524 + while (!empty($aRemainingFolders) && $copyAll) {
521 $iFolderId = array_pop($aRemainingFolders); 525 $iFolderId = array_pop($aRemainingFolders);
522 526
523 $aParams = array($iFolderId); 527 $aParams = array($iFolderId);
524 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams)); 528 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams));
525 unset($aRow['id']); 529 unset($aRow['id']);
  530 +
526 // since we are nested, we will have solved the parent first. 531 // since we are nested, we will have solved the parent first.
527 $sPrevParentId = $aRow['parent_id']; 532 $sPrevParentId = $aRow['parent_id'];
528 $aRow['parent_id'] = $aFolderMap[$aRow['parent_id']]['parent_id']; 533 $aRow['parent_id'] = $aFolderMap[$aRow['parent_id']]['parent_id'];
@@ -552,7 +557,7 @@ class KTFolderUtil { @@ -552,7 +557,7 @@ class KTFolderUtil {
552 $aCFIds = Folder::getList(array('parent_id = ?', array($iFolderId)), array('ids' => true)); 557 $aCFIds = Folder::getList(array('parent_id = ?', array($iFolderId)), array('ids' => true));
553 $aRemainingFolders = kt_array_merge($aRemainingFolders, $aCFIds); 558 $aRemainingFolders = kt_array_merge($aRemainingFolders, $aCFIds);
554 } 559 }
555 - 560 +
556 // now we can go ahead. 561 // now we can go ahead.
557 foreach ($aDocuments as $oDocument) { 562 foreach ($aDocuments as $oDocument) {
558 $oChildDestinationFolder = Folder::get($aFolderMap[$oDocument->getFolderID()]['parent_id']); 563 $oChildDestinationFolder = Folder::get($aFolderMap[$oDocument->getFolderID()]['parent_id']);
lib/permissions/permissionutil.inc.php
@@ -5,32 +5,32 @@ @@ -5,32 +5,32 @@
5 * KnowledgeTree Open Source Edition 5 * KnowledgeTree Open Source Edition
6 * Document Management Made Simple 6 * Document Management Made Simple
7 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited 7 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited
8 - * 8 + *
9 * This program is free software; you can redistribute it and/or modify it under 9 * This program is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License version 3 as published by the 10 * the terms of the GNU General Public License version 3 as published by the
11 * Free Software Foundation. 11 * Free Software Foundation.
12 - * 12 + *
13 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 * details. 16 * details.
17 - * 17 + *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 - * 20 + *
21 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, 21 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
22 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. 22 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
23 - * 23 + *
24 * The interactive user interfaces in modified source and object code versions 24 * The interactive user interfaces in modified source and object code versions
25 * of this program must display Appropriate Legal Notices, as required under 25 * of this program must display Appropriate Legal Notices, as required under
26 * Section 5 of the GNU General Public License version 3. 26 * Section 5 of the GNU General Public License version 3.
27 - * 27 + *
28 * In accordance with Section 7(b) of the GNU General Public License version 3, 28 * In accordance with Section 7(b) of the GNU General Public License version 3,
29 * these Appropriate Legal Notices must retain the display of the "Powered by 29 * these Appropriate Legal Notices must retain the display of the "Powered by
30 - * KnowledgeTree" logo and retain the original copyright notice. If the display of the 30 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
31 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices 31 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
32 - * must display the words "Powered by KnowledgeTree" and retain the original  
33 - * copyright notice. 32 + * must display the words "Powered by KnowledgeTree" and retain the original
  33 + * copyright notice.
34 * Contributor( s): ______________________________________ 34 * Contributor( s): ______________________________________
35 * 35 *
36 */ 36 */
@@ -52,6 +52,9 @@ require_once(KT_LIB_DIR . &quot;/workflow/workflowutil.inc.php&quot;); @@ -52,6 +52,9 @@ require_once(KT_LIB_DIR . &quot;/workflow/workflowutil.inc.php&quot;);
52 require_once(KT_LIB_DIR . "/workflow/workflowstatepermissionsassignment.inc.php"); 52 require_once(KT_LIB_DIR . "/workflow/workflowstatepermissionsassignment.inc.php");
53 53
54 class KTPermissionUtil { 54 class KTPermissionUtil {
  55 +
  56 + static $permArr = array();
  57 +
55 // {{{ generateDescriptor 58 // {{{ generateDescriptor
56 /** 59 /**
57 * Generate a unique textual representation of a specific collection 60 * Generate a unique textual representation of a specific collection
@@ -93,7 +96,7 @@ class KTPermissionUtil { @@ -93,7 +96,7 @@ class KTPermissionUtil {
93 $oDescriptor =& KTPermissionDescriptor::getByDescriptor(md5($sDescriptor)); 96 $oDescriptor =& KTPermissionDescriptor::getByDescriptor(md5($sDescriptor));
94 if (PEAR::isError($oDescriptor)) { 97 if (PEAR::isError($oDescriptor)) {
95 $oOriginalDescriptor = $oDescriptor; 98 $oOriginalDescriptor = $oDescriptor;
96 - 99 +
97 $oDescriptor =& KTPermissionDescriptor::createFromArray(array( 100 $oDescriptor =& KTPermissionDescriptor::createFromArray(array(
98 "descriptortext" => $sDescriptor, 101 "descriptortext" => $sDescriptor,
99 )); 102 ));
@@ -112,7 +115,7 @@ class KTPermissionUtil { @@ -112,7 +115,7 @@ class KTPermissionUtil {
112 exit(0); 115 exit(0);
113 } 116 }
114 $oDescriptor->saveAllowed($aAllowed); 117 $oDescriptor->saveAllowed($aAllowed);
115 - 118 +
116 } 119 }
117 return $oDescriptor; 120 return $oDescriptor;
118 } 121 }
@@ -193,7 +196,7 @@ class KTPermissionUtil { @@ -193,7 +196,7 @@ class KTPermissionUtil {
193 $sWhere = 'permission_object_id = ?'; 196 $sWhere = 'permission_object_id = ?';
194 $aParams = array($oPO->getID()); 197 $aParams = array($oPO->getID());
195 $aFolders =& Folder::getList(array($sWhere, $aParams)); 198 $aFolders =& Folder::getList(array($sWhere, $aParams));
196 - if (!PEAR::isError($aFolders)) { 199 + if (!PEAR::isError($aFolders)) {
197 foreach ($aFolders as $oFolder) { 200 foreach ($aFolders as $oFolder) {
198 KTPermissionUtil::updatePermissionLookup($oFolder); 201 KTPermissionUtil::updatePermissionLookup($oFolder);
199 } 202 }
@@ -253,7 +256,7 @@ class KTPermissionUtil { @@ -253,7 +256,7 @@ class KTPermissionUtil {
253 } 256 }
254 } 257 }
255 } 258 }
256 - 259 +
257 $oChannel =& KTPermissionChannel::getSingleton(); 260 $oChannel =& KTPermissionChannel::getSingleton();
258 if (is_a($oFolderOrDocument, 'Folder')) { 261 if (is_a($oFolderOrDocument, 'Folder')) {
259 $msg = sprintf("Updating folder %s", join("/", $oFolderOrDocument->getPathArray())); 262 $msg = sprintf("Updating folder %s", join("/", $oFolderOrDocument->getPathArray()));
@@ -265,7 +268,7 @@ class KTPermissionUtil { @@ -265,7 +268,7 @@ class KTPermissionUtil {
265 } 268 }
266 } 269 }
267 $oChannel->sendMessage(new KTPermissionGenericMessage($msg)); 270 $oChannel->sendMessage(new KTPermissionGenericMessage($msg));
268 - //var_dump($msg); 271 + //var_dump($msg);
269 $iPermissionObjectId = $oFolderOrDocument->getPermissionObjectID(); 272 $iPermissionObjectId = $oFolderOrDocument->getPermissionObjectID();
270 if (empty($iPermissionObjectId)) { 273 if (empty($iPermissionObjectId)) {
271 return; 274 return;
@@ -311,7 +314,7 @@ class KTPermissionUtil { @@ -311,7 +314,7 @@ class KTPermissionUtil {
311 foreach ($aWorkflowStatePermissionAssignments as $oAssignment) { 314 foreach ($aWorkflowStatePermissionAssignments as $oAssignment) {
312 $iPermissionId = $oAssignment->getPermissionId(); 315 $iPermissionId = $oAssignment->getPermissionId();
313 $iPermissionDescriptorId = $oAssignment->getDescriptorId(); 316 $iPermissionDescriptorId = $oAssignment->getDescriptorId();
314 - 317 +
315 $oPD = KTPermissionDescriptor::get($iPermissionDescriptorId); 318 $oPD = KTPermissionDescriptor::get($iPermissionDescriptorId);
316 $aGroupIDs = $oPD->getGroups(); 319 $aGroupIDs = $oPD->getGroups();
317 $aUserIDs = array(); 320 $aUserIDs = array();
@@ -330,16 +333,16 @@ class KTPermissionUtil { @@ -330,16 +333,16 @@ class KTPermissionUtil {
330 $iRoleSourceFolder = null; 333 $iRoleSourceFolder = null;
331 if (is_a($oFolderOrDocument, 'KTDocumentCore') || is_a($oFolderOrDocument, 'Document')) { $iRoleSourceFolder = $oFolderOrDocument->getFolderID(); } 334 if (is_a($oFolderOrDocument, 'KTDocumentCore') || is_a($oFolderOrDocument, 'Document')) { $iRoleSourceFolder = $oFolderOrDocument->getFolderID(); }
332 else { $iRoleSourceFolder = $oFolderOrDocument->getId(); } 335 else { $iRoleSourceFolder = $oFolderOrDocument->getId(); }
333 - 336 +
334 // very minor perf win: map role_id (in context) to PD. 337 // very minor perf win: map role_id (in context) to PD.
335 - $_roleCache = array();  
336 - 338 + $_roleCache = array();
  339 +
337 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) { 340 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
338 $aAfterRoles = array(); 341 $aAfterRoles = array();
339 if (array_key_exists('role', $aAllowed)) { 342 if (array_key_exists('role', $aAllowed)) {
340 foreach ($aAllowed['role'] as $k => $iRoleId) { 343 foreach ($aAllowed['role'] as $k => $iRoleId) {
341 // store the PD <-> RoleId map 344 // store the PD <-> RoleId map
342 - 345 +
343 // special-case "all" or "authenticated". 346 // special-case "all" or "authenticated".
344 if (($iRoleId == -3) || ($iRoleId == -4)) { 347 if (($iRoleId == -3) || ($iRoleId == -4)) {
345 $aAfterRoles[] = $iRoleId; 348 $aAfterRoles[] = $iRoleId;
@@ -366,15 +369,15 @@ class KTPermissionUtil { @@ -366,15 +369,15 @@ class KTPermissionUtil {
366 369
367 unset($aAllowed['role'][$k]); 370 unset($aAllowed['role'][$k]);
368 } 371 }
369 - 372 +
370 } 373 }
371 374
372 - unset($aMapPermAllowed[$iPermissionId]['role']);  
373 - if (!empty($aAfterRoles)) { 375 + unset($aMapPermAllowed[$iPermissionId]['role']);
  376 + if (!empty($aAfterRoles)) {
374 $aMapPermAllowed[$iPermissionId]['role'] = $aAfterRoles; 377 $aMapPermAllowed[$iPermissionId]['role'] = $aAfterRoles;
375 } 378 }
376 } 379 }
377 - 380 +
378 /* 381 /*
379 print '<pre>'; 382 print '<pre>';
380 print '=======' . $oFolderOrDocument->getName(); 383 print '=======' . $oFolderOrDocument->getName();
@@ -382,7 +385,7 @@ class KTPermissionUtil { @@ -382,7 +385,7 @@ class KTPermissionUtil {
382 var_dump($aMapPermAllowed); 385 var_dump($aMapPermAllowed);
383 print '</pre>'; 386 print '</pre>';
384 */ 387 */
385 - 388 +
386 389
387 $aMapPermDesc = array(); 390 $aMapPermDesc = array();
388 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) { 391 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
@@ -404,6 +407,7 @@ class KTPermissionUtil { @@ -404,6 +407,7 @@ class KTPermissionUtil {
404 * and so forth. 407 * and so forth.
405 */ 408 */
406 function userHasPermissionOnItem($oUser, $oPermission, $oFolderOrDocument) { 409 function userHasPermissionOnItem($oUser, $oPermission, $oFolderOrDocument) {
  410 +
407 if (is_string($oPermission)) { 411 if (is_string($oPermission)) {
408 $oPermission =& KTPermission::getByName($oPermission); 412 $oPermission =& KTPermission::getByName($oPermission);
409 } 413 }
@@ -413,20 +417,44 @@ class KTPermissionUtil { @@ -413,20 +417,44 @@ class KTPermissionUtil {
413 if (PEAR::isError($oFolderOrDocument) || $oFolderOrDocument == null) { 417 if (PEAR::isError($oFolderOrDocument) || $oFolderOrDocument == null) {
414 return false; 418 return false;
415 } 419 }
  420 +
  421 + // Quick fix for multiple permissions look ups.
  422 + // For the current lookup, if the permissions have been checked then return their value
  423 + $iPermId = $oPermission->getID();
  424 + $iDocId = $oFolderOrDocument->getID();
  425 + $lookup = 'folders';
  426 + if(is_a($oEntity, 'Document') || is_a($oEntity, 'DocumentProxy')){
  427 + $lookup = 'docs';
  428 + }
  429 + // check if permission has been set
  430 + // $permArr[permId] = array('folders' => array('id' => bool), 'docs' => array('id' => bool));
  431 + if(isset($permArr[$iPermId][$lookup][$iDocId])){
  432 + return $permArr[$iPermId][$lookup][$iDocId];
  433 + }
  434 +
  435 +
  436 +
416 $oPL = KTPermissionLookup::get($oFolderOrDocument->getPermissionLookupID()); 437 $oPL = KTPermissionLookup::get($oFolderOrDocument->getPermissionLookupID());
417 $oPLA = KTPermissionLookupAssignment::getByPermissionAndLookup($oPermission, $oPL); 438 $oPLA = KTPermissionLookupAssignment::getByPermissionAndLookup($oPermission, $oPL);
418 if (PEAR::isError($oPLA)) { 439 if (PEAR::isError($oPLA)) {
419 //print $oPL->getID(); 440 //print $oPL->getID();
  441 + $permArr[$iPermId][$lookup][$iDocId] = false;
420 return false; 442 return false;
421 } 443 }
422 $oPD = KTPermissionDescriptor::get($oPLA->getPermissionDescriptorID()); 444 $oPD = KTPermissionDescriptor::get($oPLA->getPermissionDescriptorID());
423 - 445 +
  446 + // set permission array to true
  447 + $permArr[$iPermId][$lookup][$iDocId] = true;
  448 +
  449 + // check for permissions
424 $aGroups = GroupUtil::listGroupsForUserExpand($oUser); 450 $aGroups = GroupUtil::listGroupsForUserExpand($oUser);
425 if ($oPD->hasRoles(array(-3))) { return true; } // everyone has access. 451 if ($oPD->hasRoles(array(-3))) { return true; } // everyone has access.
426 else if ($oPD->hasUsers(array($oUser))) { return true; } 452 else if ($oPD->hasUsers(array($oUser))) { return true; }
427 else if ($oPD->hasGroups($aGroups)) { return true; } 453 else if ($oPD->hasGroups($aGroups)) { return true; }
428 else if ($oPD->hasRoles(array(-4)) && !$oUser->isAnonymous()) { return true; } 454 else if ($oPD->hasRoles(array(-4)) && !$oUser->isAnonymous()) { return true; }
429 - 455 +
  456 + // permission isn't true, set to false
  457 + $permArr[$iPermId][$lookup][$iDocId] = false;
430 return false; 458 return false;
431 } 459 }
432 // }}} 460 // }}}
@@ -496,7 +524,7 @@ class KTPermissionUtil { @@ -496,7 +524,7 @@ class KTPermissionUtil {
496 'groupid' => $oOrigDC->getGroupId(), 524 'groupid' => $oOrigDC->getGroupId(),
497 'conditionid' => $oOrigDC->getConditionId(), 525 'conditionid' => $oOrigDC->getConditionId(),
498 )); 526 ));
499 - 527 +
500 $oNewDC->saveAssignment($oOrigDC->getAssignment()); 528 $oNewDC->saveAssignment($oOrigDC->getAssignment());
501 } 529 }
502 530
@@ -582,7 +610,7 @@ class KTPermissionUtil { @@ -582,7 +610,7 @@ class KTPermissionUtil {
582 $iNewPOID = $oFolder->getPermissionObjectID(); 610 $iNewPOID = $oFolder->getPermissionObjectID();
583 $oNewPO =& KTPermissionObject::get($iNewPOID); 611 $oNewPO =& KTPermissionObject::get($iNewPOID);
584 612
585 - 613 +
586 $oDocumentOrFolder->setPermissionObjectID($iNewPOID); 614 $oDocumentOrFolder->setPermissionObjectID($iNewPOID);
587 $oDocumentOrFolder->update(); 615 $oDocumentOrFolder->update();
588 616
@@ -591,7 +619,7 @@ class KTPermissionUtil { @@ -591,7 +619,7 @@ class KTPermissionUtil {
591 KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder); 619 KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder);
592 return; 620 return;
593 } 621 }
594 - 622 +
595 $iFolderID = $oDocumentOrFolder->getID(); 623 $iFolderID = $oDocumentOrFolder->getID();
596 $sFolderIDs = Folder::generateFolderIDs($iFolderID); 624 $sFolderIDs = Folder::generateFolderIDs($iFolderID);
597 $sFolderIDs .= '%'; 625 $sFolderIDs .= '%';