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 1132  
1133 1133 /**
1134 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 1140 function _folderOrDocument($path) {
1140 1141  
... ... @@ -1142,14 +1143,14 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1142 1143  
1143 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 1147 $sFileName = basename($path);
1150 1148 // for windows replace backslash with forwardslash
1151 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 1154 if ($sFolderPath == "/" || $sFolderPath == "/ktwebdav") {
1154 1155 $this->ktwebdavLog("This is the root folder.", 'info', true);
1155 1156 $sFolderPath = $this->rootFolder;
... ... @@ -1164,6 +1165,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1164 1165 $this->ktwebdavLog("sFolderName is " . $sFolderPath, 'info', true);
1165 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 1171 $aFolderNames = split('/', $sFolderPath);
1168 1172  
1169 1173 $this->ktwebdavLog("aFolderNames are: " . print_r($aFolderNames, true), 'info', true);
... ... @@ -1196,6 +1200,9 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1196 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 1206 // FIXME: Direct database access
1200 1207 // $sQuery = "SELECT id FROM documents WHERE folder_id = ? AND filename = ? AND status_id = 1";
1201 1208 $sQuery = "SELECT D.id ";
... ... @@ -1214,12 +1221,18 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1214 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 1229 if ($iDocumentID === null) {
1218 1230 $this->ktwebdavLog("iDocumentID is null", 'info', true);
1219 1231 // FIXME: Direct database access
1220 1232 $sQuery = "SELECT id FROM folders WHERE parent_id = ? AND name = ?";
1221 1233 $aParams = array($iFolderID, $sFileName);
1222 1234 $id = DBUtil::getOneResultKey(array($sQuery, $aParams), 'id');
  1235 +
1223 1236 if (PEAR::isError($id)) {
1224 1237 $this->ktwebdavLog("A DB(2) error occurred in _folderOrDocument", 'info', true);
1225 1238 return false;
... ... @@ -1235,6 +1248,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1235 1248 $this->ktwebdavLog("Setting Location Header to " . "Location: " . $_SERVER["PHP_SELF"] . "/", 'info', true);
1236 1249 header("Location: " . $_SERVER["PHP_SELF"] . "/");
1237 1250 }
  1251 + $this->ktwebdavLog("DEBUG: return id ".$id, 'info', true);
1238 1252 return array($id, null);
1239 1253 }
1240 1254  
... ... @@ -1647,24 +1661,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1647 1661  
1648 1662 /**
1649 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 1667 * @return string HTTP status code or false
1653 1668 */
1654 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 1671 $this->ktwebdavLog("Entering MOVE. options are " . print_r($options, true), 'info', true);
1667 1672  
  1673 + /* ** Check that write is allowed ** */
1668 1674 if ($this->checkSafeMode()) {
1669 1675  
1670 1676 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
... ... @@ -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 1691 $source_path = $options["path"];
1683 1692  
1684 1693 // Fix for Mac Goliath
... ... @@ -1710,22 +1719,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1710 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 1728 list($iFolderID, $iDocumentID) = $source_res;
1714   - if ($iDocumentID === false) {
  1729 + if ($iFolderID === false && ($iDocumentID === false || is_null($iDocumentID))) {
1715 1730 $this->ktwebdavLog("404 Not found - Folder was not found.", 'info', true);
1716 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 1735 // Source is a folder
  1736 + $this->ktwebdavLog("Source is a Folder.", 'info', true);
1721 1737 $movestat = $this->_MOVEFolder($options, $iFolderID);
1722 1738  
1723 1739 } else {
1724 1740 // Source is a document
  1741 + $this->ktwebdavLog("Source is a Document.", 'info', true);
1725 1742 if ($this->canCopyMoveRenameDocument($iDocumentID)) {
1726 1743 $movestat = $this->_MOVEDocument($options, $iFolderID, $iDocumentID);
1727 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 1763 */
1747 1764 function _MOVEDocument($options, $iFolderID, $iDocumentID) {
1748 1765  
  1766 + /* ** Ensure that the destination path exists ** */
1749 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 1770 // Fix for Mac Goliath
1752 1771 // Modified - 25/10/07 - remove ktwebdav from document path
... ... @@ -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 1782 global $default;
1765 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 1787 $oDocument = Document::get($iDocumentID);
1769 1788 $oSrcFolder = Folder::get($iFolderID);
1770 1789 $oUser =& User::get($this->userID);
... ... @@ -1772,36 +1791,16 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1772 1791 $source_path = $options["path"];
1773 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 1799 list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
1802 1800  
1803 1801 if (is_null($iDestDoc)) {
1804 1802 // the dest is a folder
  1803 + $this->ktwebdavLog("Destination is a folder.", 'info', true);
1805 1804 } else if ($iDestDoc !== false) {
1806 1805 // Document exists
1807 1806 $this->ktwebdavLog("Destination Document exists.", 'info', true);
... ... @@ -1822,6 +1821,39 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1822 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 1857 $oDestFolder = Folder::get($iDestFolder);
1826 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 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 1876 if ($new) {
  1877 + $this->ktwebdavLog("201 Created", 'info', true);
1884 1878 return "201 Created";
1885 1879 } else {
  1880 + $this->ktwebdavLog("204 No Content", 'info', true);
1886 1881 return "204 No Content";
1887 1882 }
1888 1883 }
... ... @@ -1897,11 +1892,13 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1897 1892 */
1898 1893 function _MOVEFolder($options, $iFolderID) {
1899 1894  
  1895 + /* ** Ensure that the destination path exists ** */
1900 1896 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
1901 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 1901 if ($options["depth"] != "infinity") {
1904   - // RFC 2518 Section 9.2, last paragraph
1905 1902 $this->ktwebdavLog("400 Bad request", 'info', true);
1906 1903 return "400 Bad request - depth must be 'inifinity'.";
1907 1904 }
... ... @@ -1920,23 +1917,75 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1920 1917  
1921 1918 global $default;
1922 1919  
  1920 + /* ** Get the relevant paths.
  1921 + Check whether the destination path refers to a folder / document. ** */
1923 1922 $source_path = $options["path"];
1924 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 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 1989 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
1941 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 2001 if (PEAR::isError($res) || is_null($res) || ($res === false)) {
1953 2002 return "404 Not Found - " . $res->getMessage();
1954 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 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 2020 $oUser =& User::get($this->userID);
1986 2021 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
1987 2022 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true);
... ... @@ -1993,18 +2028,29 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
1993 2028 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
1994 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 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 2054 * @return string HTTP status code or false
2009 2055 */
2010 2056 function COPY($options, $del = false)
... ... @@ -2012,6 +2058,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2012 2058 $this->ktwebdavLog("Entering COPY. options are " . print_r($options, true), 'info', true);
2013 2059 $this->ktwebdavLog("del is: " . $del, 'info', true);
2014 2060  
  2061 + /* ** Check that writing to the server is allowed * **/
2015 2062 if ($this->checkSafeMode()) {
2016 2063  
2017 2064 if (!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
... ... @@ -2025,6 +2072,10 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2025 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 2079 $source_path = $options["path"];
2029 2080 $this->ktwebdavLog("SourcePath is: " . $source_path, 'info', true);
2030 2081 $source_res = $this->_folderOrDocument($source_path);
... ... @@ -2033,13 +2084,19 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2033 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 2093 list($iFolderID, $iDocumentID) = $source_res;
2037   - if ($iDocumentID === false) {
  2094 + if ($iFolderID === false && ($iDocumentID === false || is_null($iDocumentID))) {
2038 2095 $this->ktwebdavLog("404 Not found - The folder could not be found.", 'info', true);
2039 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 2100 // Source is a folder
2044 2101 $this->ktwebdavLog("Source is a Folder.", 'info', true);
2045 2102 $copystat = $this->_COPYFolder($options, $iFolderID);
... ... @@ -2049,13 +2106,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2049 2106 $this->ktwebdavLog("Source is a Document.", 'info', true);
2050 2107  
2051 2108 if ($this->canCopyMoveRenameDocument($iDocumentID)) {
2052   - $copystat = $this->_COPYDocument($options, $iFolderID, $iDocumentID, $dest_folder_id);
  2109 + $copystat = $this->_COPYDocument($options, $iFolderID, $iDocumentID);
2053 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 2118 // Delete the source if this is a move and the copy was ok
2060 2119 if ($del && ($copystat{0} == "2")) {
2061 2120 $delstat = $this->DELETE(array("path" => $options["path"]));
... ... @@ -2064,6 +2123,7 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2064 2123 return $delstat;
2065 2124 }
2066 2125 }
  2126 + */
2067 2127  
2068 2128 $this->ktwebdavLog("Final copystat result is: " . $copystat, 'info', true);
2069 2129 return $copystat;
... ... @@ -2074,16 +2134,30 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2074 2134 /**
2075 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 2140 * @return string HTTP status code or false
2081 2141 */
2082 2142 function _COPYDocument($options, $iFolderID, $iDocumentID) {
2083 2143  
  2144 + /* ** Ensure that the destination path exists ** */
2084 2145 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
2085 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 2161 if ($options["depth"] != "infinity") {
2088 2162 // RFC 2518 Section 9.2, last paragraph
2089 2163 $this->ktwebdavLog("400 Bad request", 'info', true);
... ... @@ -2092,17 +2166,20 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2092 2166  
2093 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 2174 $oSrcFolder = Folder::get($iFolderID);
2099 2175  
2100   - list($iDestFolder, $iDestDoc) = $this->_folderOrDocument($dest_path);
2101   -
  2176 + $new = true;
2102 2177 if (is_null($iDestDoc)) {
2103 2178 // the dest is a folder
2104 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 2183 } else if ($iDestDoc !== false) {
2107 2184 // Document exists
2108 2185 $this->ktwebdavLog("Destination Document exists.", 'info', true);
... ... @@ -2123,25 +2200,33 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2123 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 2206 $oDestFolder = Folder::get($iDestFolder);
2127 2207 $oSrcDoc = Document::get($iDocumentID);
2128 2208  
2129 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 2214 // Check if the user has permissions to write in this folder
2135 2215 $oPerm =& KTPermission::getByName('ktcore.permissions.write');
2136 2216 $oUser =& User::get($this->userID);
2137   - if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oSrcDoc)) {
  2217 + if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
2138 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 2230 if ($new) {
2146 2231 $this->ktwebdavLog("201 Created", 'info', true);
2147 2232 return "201 Created";
... ... @@ -2160,37 +2245,52 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2160 2245 */
2161 2246 function _COPYFolder($options, $iFolderID) {
2162 2247  
  2248 + /* ** Ensure that the destination path exists ** */
2163 2249 if ($options['dest'] == '') $options["dest"] = substr($options["dest_url"], strlen($_SERVER["SCRIPT_NAME"]));
2164 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 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 2266 global $default;
2173 2267  
2174 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 2272 $source_path = $options["path"];
2177 2273 $dest_path = urldecode($options["dest"]);
2178   -
2179   - $oSrcFolder = Folder::get($iFolderID);
  2274 + $sDestPathName = basename($dest_path);
2180 2275  
2181 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 2284 $oDestFolder = Folder::get($iDestFolder);
2184 2285  
2185 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 2291 $this->ktwebdavLog("Destination Folder exists.", 'info', true);
2193   - $oReplaceFolder = Folder::get($iDestDoc);
  2292 +
  2293 + $oReplaceFolder = $oDestFolder;
2194 2294 if ($options['overwrite'] != 'T') {
2195 2295 $this->ktwebdavLog("Overwrite needs to be TRUE.", 'info', true);
2196 2296 return "412 Precondition Failed - Destination Folder exists. Overwrite needs to be TRUE.";
... ... @@ -2203,10 +2303,21 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2203 2303 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oReplaceFolder)) {
2204 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 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 2321 $oUser =& User::get($this->userID);
2211 2322 $this->ktwebdavLog("Got an oSrcFolder of " . print_r($oSrcFolder, true), 'info', true);
2212 2323 $this->ktwebdavLog("Got an oDestFolder of " . print_r($oDestFolder, true), 'info', true);
... ... @@ -2218,7 +2329,15 @@ class KTWebDAVServer extends HTTP_WebDAV_Server
2218 2329 if (!KTPermissionUtil::userHasPermissionOnItem($oUser, $oPerm, $oDestFolder)) {
2219 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 2342 if ($new) {
2224 2343 $this->ktwebdavLog("201 Created", 'info', true);
... ...
lib/documentmanagement/documentutil.inc.php
... ... @@ -638,14 +638,14 @@ class KTDocumentUtil {
638 638 return $oDocument;
639 639 }
640 640 // }}}
641   -
  641 +
642 642 function generateNewDocumentFilename($sDocFilename){
643 643 if(preg_match("/\([0-9]+\)(\.[^\.]+){1,}$/", $sDocFilename)){
644 644 preg_match("/\([0-9]+\)\./", $sDocFilename, $matches);
645 645 $new_one = substr($matches[0], 1);
646 646 $new_two = explode(')', $new_one);
647 647 $new = $new_two[0]+1;
648   -
  648 +
649 649 $pattern[0] = '/\([0-9]+\)\./';
650 650 $replacement[0] = ' ('.$new.').';
651 651 $sFilename = preg_replace($pattern, $replacement, $sDocFilename);
... ... @@ -657,27 +657,27 @@ class KTDocumentUtil {
657 657 }
658 658 $sFilename = $prefix.$suffix;
659 659 }
660   -
  660 +
661 661 return $sFilename;
662 662 }
663   -
664   - function generateNewDocumentName($sDocName){
  663 +
  664 + function generateNewDocumentName($sDocName){
665 665 if(preg_match("/\([0-9]+\)$/", $sDocName)){
666 666 preg_match("/\([0-9]+\)$/", $sDocName, $matches);
667 667 $new_one = substr($matches[0], 1);
668 668 $new_two = explode(')', $new_one);
669 669 $new = $new_two[0]+1;
670   -
  670 +
671 671 $pattern[0] = '/\([0-9]+\)$/';
672 672 $replacement[0] = '('.$new.')';
673 673 $sName = preg_replace($pattern, $replacement, $sDocName);
674 674 }else{
675 675 $sName = $sDocName.' (2)';
676 676 }
677   -
  677 +
678 678 return $sName;
679 679 }
680   -
  680 +
681 681 // {{{ fileExists
682 682 function fileExists($oFolder, $sFilename) {
683 683 return Document::fileExists($sFilename, $oFolder->getID());
... ... @@ -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 943 // 1. generate a new triad of content, metadata and core objects.
944 944 // 2. update the storage path.
945 945 //print '--------------------------------- BEFORE';
... ... @@ -958,23 +958,36 @@ class KTDocumentUtil {
958 958 // we still have a bogus md_version, but integrity holds, so fix it now.
959 959 $oCore = KTDocumentCore::get($id);
960 960  
  961 + // Get the metadata version for the source document
961 962 $sTable = KTUtil::getTableName('document_metadata_version');
962 963 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?';
963 964 $aParams = array($oDocument->getMetadataVersionId());
964 965 $aMDRow = DBUtil::getOneResult(array($sQuery, $aParams));
965 966 unset($aMDRow['id']);
  967 +
  968 + // Copy the source metadata into the destination document
966 969 $aMDRow['document_id'] = $oCore->getId();
  970 + if(!empty($sDestinationDocName)){
  971 + $aMDRow['name'] = $sDestinationDocName;
  972 + $aMDRow['description'] = $sDestinationDocName;
  973 + }
967 974 $id = DBUtil::autoInsert($sTable, $aMDRow);
968 975 if (PEAR::isError($id)) { return $id; }
969 976 $oCore->setMetadataVersionId($id);
970 977 $oMDV = KTDocumentMetadataVersion::get($id);
971 978  
  979 + // Get the content version for the source document
972 980 $sTable = KTUtil::getTableName('document_content_version');
973 981 $sQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ?';
974 982 $aParams = array($oDocument->_oDocumentContentVersion->getId());
975 983 $aContentRow = DBUtil::getOneResult(array($sQuery, $aParams));
976 984 unset($aContentRow['id']);
  985 +
  986 + // Copy the source content into the destination document
977 987 $aContentRow['document_id'] = $oCore->getId();
  988 + if(!empty($sDestinationDocName)){
  989 + $aContentRow['filename'] = $sDestinationDocName;
  990 + }
978 991 $id = DBUtil::autoInsert($sTable, $aContentRow);
979 992 if (PEAR::isError($id)) { return $id; }
980 993 $oMDV->setContentVersionId($id);
... ... @@ -996,6 +1009,7 @@ class KTDocumentUtil {
996 1009 $res = KTDocumentUtil::copyMetadata($oNewDocument, $oDocument->getMetadataVersionId());
997 1010 if (PEAR::isError($res)) { return $res; }
998 1011  
  1012 + // Ensure the copied document is not checked out
999 1013 $oNewDocument->setIsCheckedOut(false);
1000 1014 $oNewDocument->setCheckedOutUserID(-1);
1001 1015  
... ...
lib/foldermanagement/folderutil.inc.php
... ... @@ -7,32 +7,32 @@
7 7 * KnowledgeTree Open Source Edition
8 8 * Document Management Made Simple
9 9 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited
10   - *
  10 + *
11 11 * This program is free software; you can redistribute it and/or modify it under
12 12 * the terms of the GNU General Public License version 3 as published by the
13 13 * Free Software Foundation.
14   - *
  14 + *
15 15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 18 * details.
19   - *
  19 + *
20 20 * You should have received a copy of the GNU General Public License
21 21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22   - *
  22 + *
23 23 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
24 24 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
25   - *
  25 + *
26 26 * The interactive user interfaces in modified source and object code versions
27 27 * of this program must display Appropriate Legal Notices, as required under
28 28 * Section 5 of the GNU General Public License version 3.
29   - *
  29 + *
30 30 * In accordance with Section 7(b) of the GNU General Public License version 3,
31 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 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 36 * Contributor( s): ______________________________________
37 37 */
38 38  
... ... @@ -414,8 +414,9 @@ class KTFolderUtil {
414 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 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 438  
438 439 DBUtil::startTransaction();
439 440  
440   - while (!empty($aRemainingFolders)) {
  441 + while (!empty($aRemainingFolders) && $copyAll) {
441 442 $iFolderId = array_pop($aRemainingFolders);
442 443 $oFolder = Folder::get($iFolderId);
443 444 if (PEAR::isError($oFolder) || ($oFolder == false)) {
... ... @@ -487,15 +488,18 @@ class KTFolderUtil {
487 488  
488 489 $aFolderMap = array();
489 490  
490   - $sTable = KTUtil::getTableName('folders');
  491 + $sTable = 'folders';
491 492 $sGetQuery = 'SELECT * FROM ' . $sTable . ' WHERE id = ? ';
492 493 $aParams = array($oSrcFolder->getId());
493 494 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams));
494 495 unset($aRow['id']);
  496 +
  497 + $aRow['name'] = $sDestFolderName;
  498 + $aRow['description'] = $sDestFolderName;
495 499 $aRow['parent_id'] = $oDestFolder->getId();
496 500 $aRow['parent_folder_ids'] = sprintf('%s,%s', $oDestFolder->getParentFolderIDs(), $oDestFolder->getId());
497 501 $aRow['full_path'] = sprintf('%s/%s', $oDestFolder->getFullPath(), $oDestFolder->getName());
498   -
  502 +
499 503 $id = DBUtil::autoInsert($sTable, $aRow);
500 504 if (PEAR::isError($id)) {
501 505 DBUtil::rollback();
... ... @@ -506,7 +510,7 @@ class KTFolderUtil {
506 510 $aFolderMap[$sSrcFolderId]['parent_folder_ids'] = $aRow['parent_folder_ids'];
507 511 $aFolderMap[$sSrcFolderId]['full_path'] = $aRow['full_path'];
508 512 $aFolderMap[$sSrcFolderId]['name'] = $aRow['name'];
509   -
  513 +
510 514 $oNewBaseFolder = Folder::get($id);
511 515 $res = $oStorage->createFolder($oNewBaseFolder);
512 516 if (PEAR::isError($res)) {
... ... @@ -517,12 +521,13 @@ class KTFolderUtil {
517 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 525 $iFolderId = array_pop($aRemainingFolders);
522 526  
523 527 $aParams = array($iFolderId);
524 528 $aRow = DBUtil::getOneResult(array($sGetQuery, $aParams));
525 529 unset($aRow['id']);
  530 +
526 531 // since we are nested, we will have solved the parent first.
527 532 $sPrevParentId = $aRow['parent_id'];
528 533 $aRow['parent_id'] = $aFolderMap[$aRow['parent_id']]['parent_id'];
... ... @@ -552,7 +557,7 @@ class KTFolderUtil {
552 557 $aCFIds = Folder::getList(array('parent_id = ?', array($iFolderId)), array('ids' => true));
553 558 $aRemainingFolders = kt_array_merge($aRemainingFolders, $aCFIds);
554 559 }
555   -
  560 +
556 561 // now we can go ahead.
557 562 foreach ($aDocuments as $oDocument) {
558 563 $oChildDestinationFolder = Folder::get($aFolderMap[$oDocument->getFolderID()]['parent_id']);
... ...
lib/permissions/permissionutil.inc.php
... ... @@ -5,32 +5,32 @@
5 5 * KnowledgeTree Open Source Edition
6 6 * Document Management Made Simple
7 7 * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited
8   - *
  8 + *
9 9 * This program is free software; you can redistribute it and/or modify it under
10 10 * the terms of the GNU General Public License version 3 as published by the
11 11 * Free Software Foundation.
12   - *
  12 + *
13 13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 16 * details.
17   - *
  17 + *
18 18 * You should have received a copy of the GNU General Public License
19 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20   - *
  20 + *
21 21 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
22 22 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
23   - *
  23 + *
24 24 * The interactive user interfaces in modified source and object code versions
25 25 * of this program must display Appropriate Legal Notices, as required under
26 26 * Section 5 of the GNU General Public License version 3.
27   - *
  27 + *
28 28 * In accordance with Section 7(b) of the GNU General Public License version 3,
29 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 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 34 * Contributor( s): ______________________________________
35 35 *
36 36 */
... ... @@ -52,6 +52,9 @@ require_once(KT_LIB_DIR . &quot;/workflow/workflowutil.inc.php&quot;);
52 52 require_once(KT_LIB_DIR . "/workflow/workflowstatepermissionsassignment.inc.php");
53 53  
54 54 class KTPermissionUtil {
  55 +
  56 + static $permArr = array();
  57 +
55 58 // {{{ generateDescriptor
56 59 /**
57 60 * Generate a unique textual representation of a specific collection
... ... @@ -93,7 +96,7 @@ class KTPermissionUtil {
93 96 $oDescriptor =& KTPermissionDescriptor::getByDescriptor(md5($sDescriptor));
94 97 if (PEAR::isError($oDescriptor)) {
95 98 $oOriginalDescriptor = $oDescriptor;
96   -
  99 +
97 100 $oDescriptor =& KTPermissionDescriptor::createFromArray(array(
98 101 "descriptortext" => $sDescriptor,
99 102 ));
... ... @@ -112,7 +115,7 @@ class KTPermissionUtil {
112 115 exit(0);
113 116 }
114 117 $oDescriptor->saveAllowed($aAllowed);
115   -
  118 +
116 119 }
117 120 return $oDescriptor;
118 121 }
... ... @@ -193,7 +196,7 @@ class KTPermissionUtil {
193 196 $sWhere = 'permission_object_id = ?';
194 197 $aParams = array($oPO->getID());
195 198 $aFolders =& Folder::getList(array($sWhere, $aParams));
196   - if (!PEAR::isError($aFolders)) {
  199 + if (!PEAR::isError($aFolders)) {
197 200 foreach ($aFolders as $oFolder) {
198 201 KTPermissionUtil::updatePermissionLookup($oFolder);
199 202 }
... ... @@ -253,7 +256,7 @@ class KTPermissionUtil {
253 256 }
254 257 }
255 258 }
256   -
  259 +
257 260 $oChannel =& KTPermissionChannel::getSingleton();
258 261 if (is_a($oFolderOrDocument, 'Folder')) {
259 262 $msg = sprintf("Updating folder %s", join("/", $oFolderOrDocument->getPathArray()));
... ... @@ -265,7 +268,7 @@ class KTPermissionUtil {
265 268 }
266 269 }
267 270 $oChannel->sendMessage(new KTPermissionGenericMessage($msg));
268   - //var_dump($msg);
  271 + //var_dump($msg);
269 272 $iPermissionObjectId = $oFolderOrDocument->getPermissionObjectID();
270 273 if (empty($iPermissionObjectId)) {
271 274 return;
... ... @@ -311,7 +314,7 @@ class KTPermissionUtil {
311 314 foreach ($aWorkflowStatePermissionAssignments as $oAssignment) {
312 315 $iPermissionId = $oAssignment->getPermissionId();
313 316 $iPermissionDescriptorId = $oAssignment->getDescriptorId();
314   -
  317 +
315 318 $oPD = KTPermissionDescriptor::get($iPermissionDescriptorId);
316 319 $aGroupIDs = $oPD->getGroups();
317 320 $aUserIDs = array();
... ... @@ -330,16 +333,16 @@ class KTPermissionUtil {
330 333 $iRoleSourceFolder = null;
331 334 if (is_a($oFolderOrDocument, 'KTDocumentCore') || is_a($oFolderOrDocument, 'Document')) { $iRoleSourceFolder = $oFolderOrDocument->getFolderID(); }
332 335 else { $iRoleSourceFolder = $oFolderOrDocument->getId(); }
333   -
  336 +
334 337 // very minor perf win: map role_id (in context) to PD.
335   - $_roleCache = array();
336   -
  338 + $_roleCache = array();
  339 +
337 340 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
338 341 $aAfterRoles = array();
339 342 if (array_key_exists('role', $aAllowed)) {
340 343 foreach ($aAllowed['role'] as $k => $iRoleId) {
341 344 // store the PD <-> RoleId map
342   -
  345 +
343 346 // special-case "all" or "authenticated".
344 347 if (($iRoleId == -3) || ($iRoleId == -4)) {
345 348 $aAfterRoles[] = $iRoleId;
... ... @@ -366,15 +369,15 @@ class KTPermissionUtil {
366 369  
367 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 377 $aMapPermAllowed[$iPermissionId]['role'] = $aAfterRoles;
375 378 }
376 379 }
377   -
  380 +
378 381 /*
379 382 print '<pre>';
380 383 print '=======' . $oFolderOrDocument->getName();
... ... @@ -382,7 +385,7 @@ class KTPermissionUtil {
382 385 var_dump($aMapPermAllowed);
383 386 print '</pre>';
384 387 */
385   -
  388 +
386 389  
387 390 $aMapPermDesc = array();
388 391 foreach ($aMapPermAllowed as $iPermissionId => $aAllowed) {
... ... @@ -404,6 +407,7 @@ class KTPermissionUtil {
404 407 * and so forth.
405 408 */
406 409 function userHasPermissionOnItem($oUser, $oPermission, $oFolderOrDocument) {
  410 +
407 411 if (is_string($oPermission)) {
408 412 $oPermission =& KTPermission::getByName($oPermission);
409 413 }
... ... @@ -413,20 +417,44 @@ class KTPermissionUtil {
413 417 if (PEAR::isError($oFolderOrDocument) || $oFolderOrDocument == null) {
414 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 437 $oPL = KTPermissionLookup::get($oFolderOrDocument->getPermissionLookupID());
417 438 $oPLA = KTPermissionLookupAssignment::getByPermissionAndLookup($oPermission, $oPL);
418 439 if (PEAR::isError($oPLA)) {
419 440 //print $oPL->getID();
  441 + $permArr[$iPermId][$lookup][$iDocId] = false;
420 442 return false;
421 443 }
422 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 450 $aGroups = GroupUtil::listGroupsForUserExpand($oUser);
425 451 if ($oPD->hasRoles(array(-3))) { return true; } // everyone has access.
426 452 else if ($oPD->hasUsers(array($oUser))) { return true; }
427 453 else if ($oPD->hasGroups($aGroups)) { return true; }
428 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 458 return false;
431 459 }
432 460 // }}}
... ... @@ -496,7 +524,7 @@ class KTPermissionUtil {
496 524 'groupid' => $oOrigDC->getGroupId(),
497 525 'conditionid' => $oOrigDC->getConditionId(),
498 526 ));
499   -
  527 +
500 528 $oNewDC->saveAssignment($oOrigDC->getAssignment());
501 529 }
502 530  
... ... @@ -582,7 +610,7 @@ class KTPermissionUtil {
582 610 $iNewPOID = $oFolder->getPermissionObjectID();
583 611 $oNewPO =& KTPermissionObject::get($iNewPOID);
584 612  
585   -
  613 +
586 614 $oDocumentOrFolder->setPermissionObjectID($iNewPOID);
587 615 $oDocumentOrFolder->update();
588 616  
... ... @@ -591,7 +619,7 @@ class KTPermissionUtil {
591 619 KTPermissionUtil::updatePermissionLookup($oDocumentOrFolder);
592 620 return;
593 621 }
594   -
  622 +
595 623 $iFolderID = $oDocumentOrFolder->getID();
596 624 $sFolderIDs = Folder::generateFolderIDs($iFolderID);
597 625 $sFolderIDs .= '%';
... ...