From 3c133975c9c9f1616e9550a7be5aa6c9c7c4adf3 Mon Sep 17 00:00:00 2001 From: kevin_fourie Date: Wed, 9 Jan 2008 14:20:09 +0000 Subject: [PATCH] Merged in from DEV trunk... --- customerrorpage.php | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------- ktapi/KTAPIDocument.inc.php | 56 ++++++++++++++++++++++++++++++++++++++++++++------------ ktapi/KTAPIFolder.inc.php | 28 ++++++++++++++++++++++++++-- ktapi/ktapi.inc.php | 30 ++++++++++++++++++++++++++++++ ktwebservice/nunit/document_copy.cs | 59 +++++++++++++++++++++++++++++++---------------------------- ktwebservice/nunit/document_detail.cs | 10 +++++----- ktwebservice/nunit/document_metadata.cs | 32 +++++++++++++++++++++++++++++++- ktwebservice/nunit/document_move.cs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktwebservice/nunit/document_oem_no.cs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ktwebservice/nunit/document_system_metadata.cs | 32 +++++++++++++++++++++----------- ktwebservice/nunit/folder.cs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ktwebservice/nunit/helper.cs | 46 ++++++++++++++++++++++++++++++++++++++++++---- ktwebservice/nunit/makefile | 9 +++++---- ktwebservice/webservice.php | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ lib/documentmanagement/Document.inc | 21 ++++++++++++--------- lib/documentmanagement/documentcore.inc.php | 9 +++++++-- lib/documentmanagement/documentmetadataversion.inc.php | 22 +++++++++++----------- lib/foldermanagement/Folder.inc | 1 + lib/help/helpreplacement.inc.php | 24 ++++++++++++------------ lib/import/zipimportstorage.inc.php | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- lib/permissions/permissionutil.inc.php | 3 +++ plugins/housekeeper/HouseKeeperPlugin.php | 18 +++++++++++++++++- plugins/ktcore/folder/BulkUpload.php | 20 +++++++++----------- plugins/ktstandard/KTSubscriptions.php | 2 +- resources/css/errors.css | 7 +++++-- resources/js/loader.js | 6 ++++-- search2/indexing/indexerCore.inc.php | 7 ++++++- search2/search/fields/DocumentOemNoField.inc.php | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ search2/search/search.inc.php | 2 +- sql/mysql/install/structure.sql | 2 ++ sql/mysql/upgrade/3.5.2/oem_no.sql | 1 + templates/ktstandard/PDFPlugin/PDFPlugin.smarty | 6 ++++++ thirdparty/pear/File/Archive.php | 1403 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 33 files changed, 2374 insertions(+), 230 deletions(-) create mode 100644 ktwebservice/nunit/document_move.cs create mode 100644 ktwebservice/nunit/document_oem_no.cs create mode 100644 search2/search/fields/DocumentOemNoField.inc.php create mode 100644 sql/mysql/upgrade/3.5.2/oem_no.sql create mode 100644 thirdparty/pear/File/Archive.php diff --git a/customerrorpage.php b/customerrorpage.php index a427478..82ccbd8 100644 --- a/customerrorpage.php +++ b/customerrorpage.php @@ -1,56 +1,58 @@ - - - - - Knowledgetree - Desklet - - - - - - - -
- -
- - -

Error!! - You have encountered a problem starting your document management system.

-

Please contact your systems administrator

-

For more details, click here

- -
-
- - + + + + + Knowledgetree - Desklet + + + + + + + +
+ +
+ + +

Error!! - You have encountered a problem starting your document management system.

+

Please contact your systems administrator

+

For more details, click here

+ +
+
+ + \ No newline at end of file diff --git a/ktapi/KTAPIDocument.inc.php b/ktapi/KTAPIDocument.inc.php index c3df1a8..a151635 100644 --- a/ktapi/KTAPIDocument.inc.php +++ b/ktapi/KTAPIDocument.inc.php @@ -180,6 +180,12 @@ class KTAPI_Document extends KTAPI_FolderItem KTUploadManager::temporary_file_imported($tempfilename); } + function removeUpdateNotification() + { + $sql = "DELETE FROM notifications WHERE data_int_1=$this->documentid AND data_str_1='ModifyDocument'"; + DBUtil::runQuery($sql); + } + /** * Link a document to another * @@ -276,7 +282,7 @@ class KTAPI_Document extends KTAPI_FolderItem w.name as workflow, ws.name as workflow_state, dlt.name as link_type, dtl.name as document_type, - dcv.major_version, dcv.minor_version + dcv.major_version, dcv.minor_version, d.oem_no FROM document_link dl INNER JOIN document_link_types dlt ON dl.link_type_id=dlt.id @@ -312,12 +318,13 @@ class KTAPI_Document extends KTAPI_FolderItem continue; } - + $oem_no = $row['oem_no']; + if (empty($oem_no)) $oem_no = 'n/a'; $result[] = array( 'document_id'=>(int)$row['document_id'], 'custom_document_no'=>'n/a', - 'oem_document_no'=>'n/a', + 'oem_document_no'=>$oem_no, 'title'=> $row['title'], 'document_type'=> $row['document_type'], 'version'=> (float) ($row['major_version'] . '.' . $row['minor_version']), @@ -1008,9 +1015,9 @@ class KTAPI_Document extends KTAPI_FolderItem } $fieldset = KTFieldset::getByName($fieldsetname); - if (is_null($fieldset) || PEAR::isError($fieldset)) + if (is_null($fieldset) || PEAR::isError($fieldset) || is_a($fieldset, 'KTEntityNoObjects')) { - $default->log->debug("could not resolve fieldset: $fieldsetname"); + $default->log->debug("could not resolve fieldset: $fieldsetname for document id: $this->documentid"); // exit graciously continue; } @@ -1034,9 +1041,9 @@ class KTAPI_Document extends KTAPI_FolderItem } $field = DocumentField::getByFieldsetAndName($fieldset, $fieldname); - if (is_null($field) || PEAR::isError($fieldset)) + if (is_null($field) || PEAR::isError($field) || is_a($field, 'KTEntityNoObjects')) { - $default->log->debug("could not resolve field: $fieldname"); + $default->log->debug("Could not resolve field: $fieldname on fieldset $fieldsetname for document id: $this->documentid"); // exit graciously continue; } @@ -1115,6 +1122,7 @@ class KTAPI_Document extends KTAPI_FolderItem $documents = array(); $document_content = array(); $indexContent = null; + $uniqueOemNo = false; foreach($sysdata as $rec) { @@ -1135,6 +1143,13 @@ class KTAPI_Document extends KTAPI_FolderItem } switch($name) { + case 'unique_oem_document_no': + $documents['oem_no'] = $value; + $uniqueOemNo = true; + break; + case 'oem_document_no': + $documents['oem_no'] = $value; + break; case 'index_content': $indexContent = $value; break; @@ -1218,10 +1233,8 @@ class KTAPI_Document extends KTAPI_FolderItem foreach($documents as $name=>$value) { if ($i++ > 0) $sql .= ","; - if (is_numeric($value)) - $sql .= "$name=$value"; - else - $sql .= "$name='$value'"; + $value = sanitizeForSQL($value); + $sql .= "$name='$value'"; } $sql .= " WHERE id=$this->documentid"; $result = DBUtil::runQuery($sql); @@ -1229,6 +1242,14 @@ class KTAPI_Document extends KTAPI_FolderItem { return $result; } + + if ($uniqueOemNo) + { + $oem_no = sanitizeForSQL($documents['oem_no']); + $sql = "UPDATE documents SET oem_no=null WHERE oem_no = '$oem_no' AND id != $this->documentid"; + $result = DBUtil::runQuery($sql); + } + } if (count($document_content) > 0) { @@ -1238,6 +1259,7 @@ class KTAPI_Document extends KTAPI_FolderItem foreach($document_content as $name=>$value) { if ($i++ > 0) $sql .= ","; + $value = sanitizeForSQL($value); $sql .= "$name='$value'"; } $sql .= " WHERE id=$content_id"; @@ -1421,8 +1443,18 @@ class KTAPI_Document extends KTAPI_FolderItem // get the document id $detail['document_id'] = (int) $document->getId(); + $oem_document_no = null; + if ($wsversion >= 2) + { + $oem_document_no = $document->getOemNo(); + } + if (empty($oem_document_no)) + { + $oem_document_no = 'n/a'; + } + $detail['custom_document_no'] = 'n/a'; - $detail['oem_document_no'] = 'n/a'; + $detail['oem_document_no'] = $oem_document_no; // get the title $detail['title'] = $document->getName(); diff --git a/ktapi/KTAPIFolder.inc.php b/ktapi/KTAPIFolder.inc.php index 100667b..ca5c8a0 100644 --- a/ktapi/KTAPIFolder.inc.php +++ b/ktapi/KTAPIFolder.inc.php @@ -121,6 +121,7 @@ class KTAPI_Folder extends KTAPI_FolderItem */ function get_detail() { + $this->clearCache(); $detail = array( 'id'=>(int) $this->folderid, 'folder_name'=>$this->get_folder_name(), @@ -131,6 +132,17 @@ class KTAPI_Folder extends KTAPI_FolderItem return $detail; } + function clearCache() + { + // TODO: we should only clear the cache for the document we are working on + // this is a quick fix but not optimal!! + + $GLOBALS["_OBJECTCACHE"]['Folder'] = array(); + + $this->folder = &Folder::get($this->folderid); + } + + function get_parent_folder_id() { return (int) $this->folder->getParentID(); @@ -479,13 +491,16 @@ class KTAPI_Folder extends KTAPI_FolderItem $docTypeId = $document->getDocumentTypeID(); $documentType = DocumentType::get($docTypeId); + $oemDocumentNo = $document->getOemNo(); + if (empty($oemDocumentNo)) $oemDocumentNo = 'n/a'; + $contents[] = array( 'id' => (int) $document->getId(), 'item_type' => 'D', 'custom_document_no'=>'n/a', - 'oem_document_no'=>'n/a', + 'oem_document_no'=>$oemDocumentNo, 'title' => $document->getName(), 'document_type'=>$documentType->getName(), @@ -581,7 +596,16 @@ class KTAPI_Folder extends KTAPI_FolderItem $documenttypeid = KTAPI::get_documenttypeid($documenttype); if (PEAR::isError($documenttypeid)) { - return new PEAR_Error('The document type could not be resolved or is disabled: ' . $documenttype); + $config = KTCache::getSingleton(); + $defaultToDefaultDocType = $config->get('webservice/useDefaultDocumentTypeIfInvalid',true); + if ($defaultToDefaultDocType) + { + $documenttypeid = KTAPI::get_documenttypeid('Default'); + } + else + { + return new PEAR_Error('The document type could not be resolved or is disabled: ' . $documenttype); + } } diff --git a/ktapi/ktapi.inc.php b/ktapi/ktapi.inc.php index a7fbb3a..abe5caf 100644 --- a/ktapi/ktapi.inc.php +++ b/ktapi/ktapi.inc.php @@ -179,6 +179,36 @@ class KTAPI return $user; } + /** + * Search for documents matching the oem_no. + * + * Note that oem_no is associated with a document and not with version of file (document content). + * oem_no is set on a document using document::update_sysdata(). + * + * @param string $oem_no + * @param boolean idsOnly Defaults to true + * @return array + */ + function get_documents_by_oem_no($oem_no, $idsOnly=true) + { + $sql = array("SELECT id FROM documents WHERE oem_no=?",$oem_no); + $rows = DBUtil::getResultArray($sql); + if (is_null($rows) || PEAR::isError($rows)) + { + return new KTAPI_Error(KTAPI_ERROR_INTERNAL_ERROR, $rows); + } + + $result = array(); + foreach($rows as $row) + { + $documentid = $row['id']; + + $result[] = $idsOnly?$documentid:KTAPI_Document::get($this, $documentid); + } + + return $result; + } + /** * This returns a session object based on a session string. * diff --git a/ktwebservice/nunit/document_copy.cs b/ktwebservice/nunit/document_copy.cs index 0aecd0f..76f6eee 100644 --- a/ktwebservice/nunit/document_copy.cs +++ b/ktwebservice/nunit/document_copy.cs @@ -8,29 +8,29 @@ namespace MonoTests.KnowledgeTree [TestFixture] public class DocumentCopyTest : KTTest - { - private int _folderId; - private Document _doc1; + { + private int _folderId; + private Document _doc1; [SetUp] public void SetUp() - { - this._folderId = 1; + { + this._folderId = 1; this._doc1 = new Document(1, this._session, this._kt, this._verbose, false); - this._doc1.createFile(this._folderId); - - - + this._doc1.createFile(this._folderId); + + + } [TearDown] public void TearDown() { - this._doc1.deleteFile(); + this._doc1.deleteFile(); } - + [Test] public void FindDocumentBeforeCopy() { @@ -47,35 +47,38 @@ namespace MonoTests.KnowledgeTree { System.Console.WriteLine("document not found. that is ok!"); } - } - + } + [Test] public void CopyTest() { - kt_document_detail linkresp = this._kt.copy_document(this._session, this._doc1.docId, 1, "copy", "test123", "test123.txt"); - Assert.AreEqual(0, linkresp.status_code); - Assert.AreEqual("test123.txt", linkresp.filename); - Assert.AreEqual("test123", linkresp.title); + kt_folder_detail response2 = this._kt.create_folder(this._session, 1, "kt_unit_test_move"); + Assert.AreEqual(0,response2.status_code); + int folderId = response2.id; + + + kt_document_detail linkresp = this._kt.copy_document(this._session, this._doc1.docId, folderId, "copy", ""); + Assert.AreEqual(0, linkresp.status_code); + Assert.AreEqual("kt_unit_test1.txt", linkresp.filename); + Assert.AreEqual("kt unit test1", linkresp.title); + - } - + [Test] public void FindDocumentAfterCopy() { - String filename = "Root Folder/test123"; + String filename = "Root Folder/kt unit test1"; if (this._verbose) System.Console.WriteLine("Finding document before add: " + filename); kt_document_detail documentDetail = this._kt.get_document_detail_by_title(this._session, 1, filename, ""); - Assert.AreEqual(0, documentDetail.status_code); - - if (this._verbose) System.Console.WriteLine("Found document - deleting"); - kt_response response = this._kt.delete_document(this._session, documentDetail.document_id, "Delete - cleaning up before add"); - Assert.AreEqual(0, response.status_code); - - } - + Assert.AreEqual(0, documentDetail.status_code); + + + + } + } diff --git a/ktwebservice/nunit/document_detail.cs b/ktwebservice/nunit/document_detail.cs index 3ab6eb3..fa41138 100644 --- a/ktwebservice/nunit/document_detail.cs +++ b/ktwebservice/nunit/document_detail.cs @@ -108,7 +108,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual(null, response.transitions); } - //[Test] + [Test] public void GetDetailByTitleTest() { kt_document_detail response = this._kt.get_document_detail_by_name(this._session, 1, "Root Folder/kt unit test1", "T",""); @@ -118,7 +118,7 @@ namespace MonoTests.KnowledgeTree } - //[Test] + [Test] public void GetDetailByTitle2Test() { kt_document_detail response = this._kt.get_document_detail_by_title(this._session, 1, "Root Folder/kt unit test1", ""); @@ -127,7 +127,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual(this._docId, response.document_id); } - //[Test] + [Test] public void GetDetailByFileTest() { kt_document_detail response = this._kt.get_document_detail_by_name(this._session, 1, "Root Folder/kt_unit_test1.txt", "F",""); @@ -135,7 +135,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual(0, response.status_code); Assert.AreEqual(this._docId, response.document_id); } - //[Test] + [Test] public void GetDetailByFile2Test() { kt_document_detail response = this._kt.get_document_detail_by_filename(this._session, 1, "Root Folder/kt_unit_test1.txt", ""); @@ -144,7 +144,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual(this._docId, response.document_id); } - //[Test] + [Test] public void GetDetailByUnknownNameTest() { kt_document_detail response = this._kt.get_document_detail_by_name(this._session, 1, "Root Folder/kt_unit_test1.ssssdasdasd", "F",""); diff --git a/ktwebservice/nunit/document_metadata.cs b/ktwebservice/nunit/document_metadata.cs index af29019..39bb5cc 100644 --- a/ktwebservice/nunit/document_metadata.cs +++ b/ktwebservice/nunit/document_metadata.cs @@ -139,11 +139,41 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual("Media Type", update_resp.metadata[1].fields[2].name); Assert.AreEqual("Text'", update_resp.metadata[1].fields[2].value); + } + [Test] + public void ProblemMetadataNoFieldSetTest() + { + kt_metadata_fieldset[] fs = new kt_metadata_fieldset[1]; + fs[0] = new kt_metadata_fieldset(); + fs[0].fieldset = "UnknownFieldset"; + fs[0].fields = new kt_metadata_field[1]; + fs[0].fields[0] = new kt_metadata_field(); + fs[0].fields[0].name = "Document Author"; + fs[0].fields[0].value = "Joe \\Soap"; - } + kt_sysdata_item[] sysdata = new kt_sysdata_item[0]; + + kt_document_detail update_resp = this._kt.update_document_metadata(this._session, this._docId, fs, sysdata); + Assert.AreEqual(0, update_resp.status_code); + } + [Test] + public void ProblemMetadataNoFieldTest() + { + kt_metadata_fieldset[] fs = new kt_metadata_fieldset[1]; + fs[0] = new kt_metadata_fieldset(); + fs[0].fieldset = "General information"; + fs[0].fields = new kt_metadata_field[1]; + fs[0].fields[0] = new kt_metadata_field(); + fs[0].fields[0].name = "Document Owner"; + fs[0].fields[0].value = "Joe \\Soap"; + + kt_sysdata_item[] sysdata = new kt_sysdata_item[0]; + kt_document_detail update_resp = this._kt.update_document_metadata(this._session, this._docId, fs, sysdata); + Assert.AreEqual(0, update_resp.status_code); + } } } diff --git a/ktwebservice/nunit/document_move.cs b/ktwebservice/nunit/document_move.cs new file mode 100644 index 0000000..d5b12a0 --- /dev/null +++ b/ktwebservice/nunit/document_move.cs @@ -0,0 +1,93 @@ +using NUnit.Framework; +using System; +using System.IO; + +namespace MonoTests.KnowledgeTree +{ + + + [TestFixture] + public class DocumentMoveTest : KTTest + { + private int _folderId; + private Document _doc1; + + private int _folderId2; + + [SetUp] + public void SetUp() + { + this._folderId = 1; + + this._doc1 = new Document(1, this._session, this._kt, this._verbose, false); + this._doc1.createFile(this._folderId); + + + + } + + [TearDown] + public void TearDown() + { + this._doc1.deleteFile(); + } + + [Test] + public void FindDocumentBeforeMove() + { + String filename = "Root Folder/test123move"; + if (this._verbose) System.Console.WriteLine("Finding document before add: " + filename); + kt_document_detail documentDetail = this._kt.get_document_detail_by_title(this._session, 1, filename, ""); + if (0 == documentDetail.status_code) + { + if (this._verbose) System.Console.WriteLine("Found document - deleting"); + kt_response response = this._kt.delete_document(this._session, documentDetail.document_id, "Delete - cleaning up before add"); + Assert.AreEqual(0, response.status_code); + } + else if (this._verbose) + { + System.Console.WriteLine("document not found. that is ok!"); + } + + + } + + + [Test] + public void MoveTest() + { + kt_folder_detail response2 = this._kt.create_folder(this._session, 1, "kt_unit_test_move"); + Assert.AreEqual(0,response2.status_code); + int folderId = _folderId2 =response2.id; + + System.Console.WriteLine("The folder id is: " +folderId); + + + System.Console.WriteLine("The document id is: " +this._doc1.docId); + + kt_document_detail linkresp = this._kt.move_document(this._session, this._doc1.docId, folderId, "move ", ""); + Assert.AreEqual(0, linkresp.status_code); + Assert.AreEqual("kt_unit_test1.txt", linkresp.filename); + Assert.AreEqual("kt unit test1", linkresp.title); + Assert.AreEqual(folderId, linkresp.folder_id); + + + + } + + [Test] + public void FindDocumentAfterMove() + { + String filename = "Root Folder/kt unit test1"; + if (this._verbose) System.Console.WriteLine("Finding document before add: " + filename); + kt_document_detail documentDetail = this._kt.get_document_detail_by_title(this._session, 1, filename, ""); + Assert.AreEqual(0, documentDetail.status_code); + + + + } + + + + } +} diff --git a/ktwebservice/nunit/document_oem_no.cs b/ktwebservice/nunit/document_oem_no.cs new file mode 100644 index 0000000..48a9e9e --- /dev/null +++ b/ktwebservice/nunit/document_oem_no.cs @@ -0,0 +1,91 @@ +using NUnit.Framework; +using System; +using System.IO; + +namespace MonoTests.KnowledgeTree +{ + [TestFixture] + public class DocumentOemNoTest : KTTest + { + private int _docId; + private int _folderId; + private String _filename; + private String _content; + + + [SetUp] + public void SetUp() + { + this._filename = Helper.isUnix()?"/tmp/kt_unit_test1.txt":"c:\\kt_unit_test1.txt"; + + String filename = "kt unit test1"; + + this._content = "hello world!"; + + Helper.writeFile(this._filename, this._content); + + this._folderId = 1; + + kt_document_detail response1 = this._kt.add_base64_document(this._session, this._folderId, filename, this._filename, "Default", Helper.ConvertFileToBase64Encoding(this._filename)); + + if (this._verbose && response1.status_code != 0) + { + System.Console.WriteLine("Could not create file: " + this._filename); + } + this._docId = response1.document_id; + } + + [TearDown] + public void TearDown() + { + + Helper.deleteFile(this._filename); + + kt_response response = this._kt.delete_document(this._session, this._docId, "Delete - cleaning up"); + if (this._verbose && response.status_code != 0) + { + System.Console.WriteLine("Could not delete file: " + this._filename); + } + } + + [Test] + public void UpdateOemNoMetadataTest() + { + kt_metadata_fieldset[] fs = new kt_metadata_fieldset[0]; + + kt_sysdata_item[] sysdata = new kt_sysdata_item[1]; + sysdata[0] = new kt_sysdata_item(); + sysdata[0].name = "oem_document_no"; + sysdata[0].value = "1234"; + + kt_document_detail update_resp = this._kt.update_document_metadata(this._session, this._docId, fs, sysdata); + Assert.AreEqual(0, update_resp.status_code); + + Assert.AreEqual("1234", update_resp.oem_document_no); + } + + [Test] + public void UpdateUniqueOemNoMetadataTest() + { + kt_metadata_fieldset[] fs = new kt_metadata_fieldset[0]; + + kt_sysdata_item[] sysdata = new kt_sysdata_item[1]; + sysdata[0] = new kt_sysdata_item(); + sysdata[0].name = "unique_oem_document_no"; + sysdata[0].value = "1234"; + + kt_document_detail update_resp = this._kt.update_document_metadata(this._session, this._docId, fs, sysdata); + Assert.AreEqual(0, update_resp.status_code); + + Assert.AreEqual("1234", update_resp.oem_document_no); + + + kt_document_collection_response response = this._kt.get_documents_by_oem_no(this._session, "1234", ""); + + Assert.AreEqual(1, response.collection.Length); + Assert.AreEqual(this._docId, response.collection[0].document_id); + Assert.AreEqual("1234", response.collection[0].oem_document_no); + + } + } +} diff --git a/ktwebservice/nunit/document_system_metadata.cs b/ktwebservice/nunit/document_system_metadata.cs index 5c4b419..494e072 100644 --- a/ktwebservice/nunit/document_system_metadata.cs +++ b/ktwebservice/nunit/document_system_metadata.cs @@ -32,7 +32,7 @@ namespace MonoTests.KnowledgeTree this._doc2.deleteFile(); } -// [Test] + [Test] public void UpdateDocumentMetadataTest() { @@ -81,7 +81,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual("2007-01-17 00:00:00", update_resp.created_date); } -// [Test] + [Test] public void AddSmallDocumentWithMetadataTest() { kt_metadata_fieldset[] fs = new kt_metadata_fieldset[1]; @@ -125,7 +125,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual("2007-01-17 00:00:00", update_resp.created_date); } -// [Test] + [Test] public void CheckinSmallDocumentWithMetadataTest() { kt_metadata_fieldset[] fs = new kt_metadata_fieldset[1]; @@ -172,7 +172,7 @@ namespace MonoTests.KnowledgeTree Assert.AreEqual("Anonymous", update_resp.created_by); Assert.AreEqual("2007-01-17 00:00:00", update_resp.created_date); } - + [Test] public void AddDocumentWithMetadataTest() { @@ -190,7 +190,7 @@ namespace MonoTests.KnowledgeTree fs[0].fields[2].name = "Media Type"; fs[0].fields[2].value = "Text"; - kt_sysdata_item[] sysdata = new kt_sysdata_item[2]; + kt_sysdata_item[] sysdata = new kt_sysdata_item[3]; sysdata[0] = new kt_sysdata_item(); sysdata[0].name = "created_by"; sysdata[0].value = "Anonymous"; @@ -199,19 +199,29 @@ namespace MonoTests.KnowledgeTree sysdata[1].value = "2007-01-17"; + sysdata[2] = new kt_sysdata_item(); + sysdata[2].name = "index_content"; + sysdata[2].value = "happy happy. this is a test with hippos and rhinos under the sun. unbrellas are required to create shade when trees are not abound."; + + this._doc2.local = true; this._doc2.createFile(this._folderId); - + + + for (int i =0;i<2;i++) + { FileUploader uploader = new FileUploader( ); uploader.upload(this._session, this._doc2.filename); - + System.Console.WriteLine("uploaded: " + uploader.filename); - kt_document_detail response1 = this._kt.add_document_with_metadata(this._session, this._folderId, this._doc2.title, this._doc2.filename, "Default", uploader.filename,fs, sysdata); - Assert.AreEqual(0, response1.status_code); + kt_document_detail response1 = this._kt.add_document_with_metadata(this._session, this._folderId, this._doc2.title+i, this._doc2.filename+i, "Default", uploader.filename,fs, sysdata); + + Assert.AreEqual(0, response1.status_code); + } } [Test] @@ -246,8 +256,8 @@ namespace MonoTests.KnowledgeTree uploader.upload(this._session, this._doc1.filename); - kt_document_detail update_resp = this._kt.checkin_document(this._session, this._doc1.docId, this._doc1.filename, "unit test - doing checkin", uploader.filename, false); - Assert.AreEqual(0, update_resp.status_code); + kt_document_detail update_resp = this._kt.checkin_document(this._session, this._doc1.docId, this._doc1.filename, "unit test - doing checkin", uploader.filename, false); + Assert.AreEqual(0, update_resp.status_code); } } diff --git a/ktwebservice/nunit/folder.cs b/ktwebservice/nunit/folder.cs index 7279ebb..879659a 100644 --- a/ktwebservice/nunit/folder.cs +++ b/ktwebservice/nunit/folder.cs @@ -49,6 +49,9 @@ namespace MonoTests.KnowledgeTree } + + + [Test] public void GetFolderByName() { @@ -122,6 +125,55 @@ namespace MonoTests.KnowledgeTree response = this._kt.create_folder(this._session, 1, "kt - unit - test"); Assert.AreEqual(0,response.status_code); Assert.AreEqual("kt - unit - test",response.folder_name); + + response = this._kt.get_folder_detail_by_name(this._session, "/kt ' unit \" test"); + Assert.AreEqual(0,response.status_code); + Assert.AreEqual("kt ' unit \" test",response.folder_name); } + + [Test] + public void CopyFolder() + { + + kt_folder_detail response = this._kt.create_folder(this._session, 1, "kt_unit_test2"); + Assert.AreEqual(0,response.status_code); + + this._folder_id = response.id; + + response = this._kt.create_folder(this._session, 1, "subfolder"); + Assert.AreEqual(0,response.status_code); + + this._subfolder_id = response.id; + + + response = this._kt.copy_folder(this._session, this._folder_id, this._subfolder_id, "copy reason"); + Assert.AreEqual(0,response.status_code); + Assert.AreEqual(this._subfolder_id,response.parent_id); + Assert.AreEqual("kt_unit_test2",response.folder_name); + + } + + [Test] + public void MoveFolder() + { + + kt_folder_detail response = this._kt.create_folder(this._session, 1, "kt_unit_test3"); + Assert.AreEqual(0,response.status_code); + + this._folder_id = response.id; + + response = this._kt.create_folder(this._session, 1, "subfolder3"); + Assert.AreEqual(0,response.status_code); + + this._subfolder_id = response.id; + + response = this._kt.move_folder(this._session, this._folder_id, this._subfolder_id, "move reason"); + Assert.AreEqual(0,response.status_code); + Assert.AreEqual(this._folder_id,response.id); + Assert.AreEqual(this._subfolder_id,response.parent_id); + Assert.AreEqual("kt_unit_test3",response.folder_name); + } + + } } diff --git a/ktwebservice/nunit/helper.cs b/ktwebservice/nunit/helper.cs index 35a3886..dbe2832 100644 --- a/ktwebservice/nunit/helper.cs +++ b/ktwebservice/nunit/helper.cs @@ -4,7 +4,28 @@ using System.Net; using System.IO; using System.Collections; using System.Data; -using System.Data.Odbc; +using System.Data.Odbc; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Messaging; +using System.Runtime.Remoting.Activation; +using System.Runtime.Remoting.Services; +using System.Runtime.Serialization; +using System.Text.RegularExpressions; +using System.Web.Services.Protocols; +using System.Reflection; +using Interception; +using System.Web; +using System.Xml; +using System.Web.Services; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Web.Services.Description; +using System.Web.Services.Discovery; +using System.Xml.Serialization; +using System.Xml.Schema; +using System.Threading; +using System.Web.Services.Protocols; namespace MonoTests.KnowledgeTree { @@ -18,7 +39,22 @@ namespace MonoTests.KnowledgeTree { this.Url = Environment.GetEnvironmentVariable("KT_ROOT_URL") + "/ktwebservice/webservice.php"; } - } + } + + public class MySoapHttpClientProtocol : SoapHttpClientProtocol + { + public MySoapHttpClientProtocol() : base() {} + + public object [] ReceiveResponse (WebResponse response, SoapClientMessage message, SoapExtension[] extensions) + { + + StreamReader sr = new StreamReader(response.GetResponseStream()); + String content = sr.ReadToEnd(); + System.Console.WriteLine(content); + + return null; + } + } public class KTTest { @@ -33,8 +69,10 @@ namespace MonoTests.KnowledgeTree kt_response response = this._kt.login("admin","admin","127.0.0.1"); this._session = response.message; this._verbose = false; - this.setupDb(); - } + this.setupDb(); + + //System.Web.Services.Protocols.SoapHttpClientProtocol.ReceiveResponse + } void setupDb() { diff --git a/ktwebservice/nunit/makefile b/ktwebservice/nunit/makefile index 236c43d..73cf630 100644 --- a/ktwebservice/nunit/makefile +++ b/ktwebservice/nunit/makefile @@ -1,15 +1,16 @@ -RESULTS= authentication.result document_detail.result document_contents.result document_history.result folder.result document_metadata.result document_add.result document_checkout.result document_type.result document_links.result document_owner.result document_rename.result document_workflow.result document_copy.result document_system_metadata.result query.result document_download.result +RESULTS=folder.result document_metadata.result authentication.result document_contents.result document_detail.result document_history.result document_add.result document_checkout.result document_links.result document_owner.result document_rename.result document_workflow.result document_copy.result document_move.result document_system_metadata.result query.result document_download.result document_type.result document_oem_no.result PROXY=KTproxy.cs WSDL=ktdms.wsdl ROOT_URL=http://ktdms.trunk +#ROOT_URL=http://192.168.1.111 WSDL_URL=${ROOT_URL}/ktwebservice/index.php?wsdl all: ${RESULTS} results: clean-results ${RESULTS} -KTproxy.dll: KTproxy.cs helper.cs - mcs -r:System.Web.Services -r:System.Data.dll /target:library KTproxy.cs helper.cs +KTproxy.dll: KTproxy.cs helper.cs + mcs -r:System.Web.Services -r:System.Data.dll /target:library KTproxy.cs intercept.cs helper.cs KTproxy.cs: ktdms.wsdl wsdl -out:${PROXY} ${WSDL} @@ -23,7 +24,7 @@ clean: clean-results: rm -f ${RESULTS} -%.dll: %.cs KTproxy.dll +%.dll: %.cs KTproxy.dll mcs -r:System.Web.Services -r:nunit.framework /r:KTproxy.dll -debug /target:library -out:$@ $< %.result: %.dll diff --git a/ktwebservice/webservice.php b/ktwebservice/webservice.php index ade51f9..e16eb00 100644 --- a/ktwebservice/webservice.php +++ b/ktwebservice/webservice.php @@ -69,6 +69,7 @@ if (defined('HAS_SEARCH_FUNCTIONALITY')) // TODO: redo metadata encoding // TODO: unit tests - metadata - test return values in selectin - list/tree // TODO: ktwsapi/php must be made compatible with v2/v3 +// TODO: subscriptions/notifications // NOTE: some features are not implemented yet. most expected for v3. e.g. oem_document_no, custom_document_no, download($version)., get_metadata($version) @@ -555,6 +556,34 @@ class KTWebService ); } + $this->__typedef["{urn:$this->namespace}kt_document_collection"] = + array( + array( + 'item' => "{urn:$this->namespace}kt_document_detail" + ) + ); + + $this->__typedef["{urn:$this->namespace}kt_document_collection_response"] = + array( + 'status_code' => 'int', + 'message' => 'string', + 'collection' => "{urn:$this->namespace}kt_document_collection" + ); + + $this->__typedef["{urn:$this->namespace}kt_folder_collection"] = + array( + array( + 'item' => "{urn:$this->namespace}kt_folder_detail" + ) + ); + + $this->__typedef["{urn:$this->namespace}kt_folder_collection_response"] = + array( + 'status_code' => 'int', + 'message' => 'string', + 'collection' => "{urn:$this->namespace}kt_folder_collection" + ); + $this->__typedef["{urn:$this->namespace}kt_document_version_history"] = array( array( @@ -642,6 +671,12 @@ class KTWebService $this->__dispatch_map['get_folder_detail']['in'] = array('session_id' => 'string', 'folder_id' => 'int', 'create'=>'boolean' ); } + // get_documents_by_oem_no + $this->__dispatch_map['get_documents_by_oem_no'] = + array('in' => array('session_id' => 'string', 'oem_no' => 'string', 'detail' => 'string'), + 'out' => array('return' => "{urn:$this->namespace}kt_document_collection_response"), + ); + // get_folder_detail_by_name $this->__dispatch_map['get_folder_detail_by_name'] = array('in' => array('session_id' => 'string', 'folder_name' => 'string' ), @@ -712,12 +747,23 @@ class KTWebService 'out' => array('return' => "{urn:$this->namespace}kt_response" ), ); + if ($this->version >= 2) + { + $this->__dispatch_map['copy_folder']['out'] = array('return' => "{urn:$this->namespace}kt_folder_detail" ); + } + // move_folder $this->__dispatch_map['move_folder'] = array('in' => array('session_id'=>'string','source_id'=>'int','target_id'=>'int','reason' =>'string'), 'out' => array('return' => "{urn:$this->namespace}kt_response" ), ); + if ($this->version >= 2) + { + $this->__dispatch_map['move_folder']['out'] = array('return' => "{urn:$this->namespace}kt_folder_detail" ); + } + + // get_document_detail $this->__dispatch_map['get_document_detail'] = array( 'in' => array('session_id' => 'string', 'document_id' => 'int' ), @@ -914,7 +960,10 @@ class KTWebService ); if ($this->version >= 2) { - $this->__dispatch_map['copy_document']['out'] = array( 'return' => "{urn:$this->namespace}kt_document_detail" ); + $this->__dispatch_map['copy_document'] = + array('in' => array('session_id'=>'string','document_id'=>'int','folder_id'=>'int','reason'=>'string', 'options'=>'string' ), + 'out' => array( 'return' => "{urn:$this->namespace}kt_document_detail" ), + ); } // move_document @@ -924,7 +973,10 @@ class KTWebService ); if ($this->version >= 2) { - $this->__dispatch_map['move_document']['out'] = array( 'return' => "{urn:$this->namespace}kt_document_detail" ); + $this->__dispatch_map['move_document'] = + array('in' => array('session_id'=>'string','document_id'=>'int','folder_id'=>'int','reason'=>'string', 'options'=>'string'), + 'out' => array( 'return' => "{urn:$this->namespace}kt_document_detail" ), + ); } // rename_document_title @@ -1493,9 +1545,15 @@ class KTWebService { $this->debug("copy_folder('$session_id',$source_id,$target_id,'$reason')"); $kt = &$this->get_ktapi($session_id ); + + $responseType = 'kt_response'; + if ($this->version >= 2) + { + $responseType = 'kt_folder_detail'; + } if (is_array($kt)) { - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $kt); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $kt); } $response = KTWebService::_status(KTWS_ERR_INVALID_FOLDER); @@ -1505,7 +1563,7 @@ class KTWebService { $response['message'] = $src_folder->getMessage(); $this->debug("copy_folder - cannot get source folderid $source_id - " . $src_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $tgt_folder = &$kt->get_folder_by_id($target_id); @@ -1514,7 +1572,7 @@ class KTWebService $response['message'] = $tgt_folder->getMessage(); $this->debug("copy_folder - cannot get target folderid $target_id - " . $tgt_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $result= $src_folder->copy($tgt_folder, $reason); @@ -1524,12 +1582,23 @@ class KTWebService $response['message'] = $result->getMessage(); $this->debug("copy_folder - copy to target folder - " . $result->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); + } + + if ($this->version >=2) + { + + $sourceName = $src_folder->get_folder_name(); + $targetPath = $tgt_folder->get_full_path(); + + $response = $this->get_folder_detail_by_name($session_id, $targetPath . '/' . $sourceName); + + return $response; } $response['status_code']= KTWS_SUCCESS; - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } /** @@ -1545,9 +1614,14 @@ class KTWebService { $this->debug("move_folder('$session_id',$source_id,$target_id,'$reason')"); $kt = &$this->get_ktapi($session_id ); + $responseType = 'kt_response'; + if ($this->version >= 2) + { + $responseType = 'kt_folder_detail'; + } if (is_array($kt)) { - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $kt); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $kt); } $response = KTWebService::_status(KTWS_ERR_INVALID_FOLDER); @@ -1557,7 +1631,7 @@ class KTWebService { $response['message'] = $src_folder->getMessage(); $this->debug("move_folder - cannot get source folder $source_id - " . $src_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $tgt_folder = &$kt->get_folder_by_id($target_id); @@ -1565,7 +1639,7 @@ class KTWebService { $response['message'] = $tgt_folder->getMessage(); $this->debug("move_folder - cannot get target folder $target_id - " . $tgt_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $result = $src_folder->move($tgt_folder, $reason); @@ -1574,12 +1648,20 @@ class KTWebService $response['status_code'] = KTWS_ERR_PROBLEM; $response['message'] = $result->getMessage(); $this->debug("move_folder - cannot move folder - " . $result->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); + } + + if ($this->version >=2) + { + + $response = $this->get_folder_detail($session_id, $source_id); + + return $response; } $response['status_code']= KTWS_SUCCESS; - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } /** @@ -1908,6 +1990,11 @@ class KTWebService } $document = $kt->get_document_by_id($document_id); + $result = $document->removeUpdateNotification(); + if (PEAR::isError($result)) + { + // not much we can do, maybe just log! + } $result = $document->mergeWithLastMetadataVersion(); if (PEAR::isError($result)) { @@ -1942,6 +2029,13 @@ class KTWebService } $document = $kt->get_document_by_id($document_id); + $result = $document->removeUpdateNotification(); + if (PEAR::isError($result)) + { + // not much we can do, maybe just log! + } + + $result = $document->mergeWithLastMetadataVersion(); if (PEAR::isError($result)) { @@ -1951,6 +2045,45 @@ class KTWebService return $update_result; } + + /** + * Find documents matching the document oem (integration) no + * + * @param string $session_id + * @param string $oem_no + * @param string $detail + * @return kt_document_collection_response + */ + function get_documents_by_oem_no($session_id, $oem_no, $detail) + { + $this->debug("get_documents_by_oem_no('$session_id','$oem_no', '$detail')"); + $kt = &$this->get_ktapi($session_id ); + if (is_array($kt)) + { + return new SOAP_Value('return',"{urn:$this->namespace}kt_document_collection_response", $kt); + } + + $documents = $kt->get_documents_by_oem_no($oem_no); + + $collection = array(); + foreach($documents as $documentId) + { + $detail = $this->get_document_detail($session_id, $documentId, $detail); + if ($detail->value['status_code'] != 0) + { + continue; + } + $collection[] = $detail->value; + } + + $response=array(); + $response['status_code'] = KTWS_SUCCESS; + $response['message'] = empty($collection)?_kt('No documents were found matching the specified document no'):''; + $response['collection'] = new SOAP_Value('collection',"{urn:$this->namespace}kt_document_collection", $collection); + + return new SOAP_Value('return',"{urn:$this->namespace}kt_document_collection_response", $response); + } + /** * Adds a document to the repository. * @@ -2088,6 +2221,11 @@ class KTWebService } $document = $kt->get_document_by_id($document_id); + $result = $document->removeUpdateNotification(); + if (PEAR::isError($result)) + { + // not much we can do, maybe just log! + } $result = $document->mergeWithLastMetadataVersion(); if (PEAR::isError($result)) { @@ -2121,6 +2259,11 @@ class KTWebService } $document = $kt->get_document_by_id($document_id); + $result = $document->removeUpdateNotification(); + if (PEAR::isError($result)) + { + // not much we can do, maybe just log! + } $result = $document->mergeWithLastMetadataVersion(); if (PEAR::isError($result)) { @@ -2583,14 +2726,19 @@ class KTWebService * @param string $newfilename * @return kt_document_detail */ - function copy_document($session_id,$document_id,$folder_id,$reason,$newtitle,$newfilename) + function copy_document($session_id,$document_id,$folder_id,$reason,$newtitle=null,$newfilename=null) { $this->debug("copy_document('$session_id',$document_id,$folder_id,'$reason','$newtitle','$newfilename')"); + $responseType = 'kt_response'; + if ($this->version >= 2) + { + $responseType = 'kt_document_detail'; + } $kt = &$this->get_ktapi($session_id ); if (is_array($kt)) { - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $kt); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $kt); } $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT); @@ -2600,7 +2748,7 @@ class KTWebService { $response['message'] = $document->getMessage(); $this->debug("copy_document - cannot get documentid $document_id - " . $document->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $tgt_folder = &$kt->get_folder_by_id($folder_id); @@ -2609,7 +2757,7 @@ class KTWebService $response['status_code'] = KTWS_ERR_INVALID_FOLDER; $response['message'] = $tgt_folder->getMessage(); $this->debug("copy_document - cannot get folderid $folder_id - " . $tgt_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $result = $document->copy($tgt_folder, $reason, $newtitle, $newfilename); @@ -2617,7 +2765,7 @@ class KTWebService { $response['message'] = $result->getMessage(); $this->debug("copy_document - cannot copy - " . $result->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $response['status_code'] = KTWS_SUCCESS; if ($this->version >= 2) @@ -2626,7 +2774,7 @@ class KTWebService return $this->get_document_detail($session_id, $new_document_id, ''); } - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } /** @@ -2640,13 +2788,18 @@ class KTWebService * @param string $newfilename * @return kt_response */ - function move_document($session_id,$document_id,$folder_id,$reason,$newtitle,$newfilename) + function move_document($session_id,$document_id,$folder_id,$reason,$newtitle=null,$newfilename=null) { $this->debug("move_document('$session_id',$document_id,$folder_id,'$reason','$newtitle','$newfilename')"); + $responseType = 'kt_response'; + if ($this->version >= 2) + { + $responseType = 'kt_document_detail'; + } $kt = &$this->get_ktapi($session_id ); if (is_array($kt)) { - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $kt); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $kt); } $response = KTWebService::_status(KTWS_ERR_INVALID_DOCUMENT); @@ -2656,16 +2809,20 @@ class KTWebService { $response['message'] = $document->getMessage(); $this->debug("move_document - cannot get documentid $document_id - " . $document->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } + if ($document->ktapi_folder->folderid != $folder_id) + { + // we only have to do something if the source and target folders are different + $tgt_folder = &$kt->get_folder_by_id($folder_id); if (PEAR::isError($tgt_folder)) { $response['status_code'] = KTWS_ERR_INVALID_FOLDER; $response['message'] = $tgt_folder->getMessage(); $this->debug("move_document - cannot get folderid $folder_id - " . $tgt_folder->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } $result = $document->move($tgt_folder, $reason, $newtitle, $newfilename); @@ -2673,11 +2830,17 @@ class KTWebService { $response['message'] = $result->getMessage(); $this->debug("move_document - cannot move - " . $result->getMessage(), $session_id); - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); + } } + $response['status_code'] = KTWS_SUCCESS; + if ($this->version >= 2) + { + return $this->get_document_detail($session_id, $document_id, ''); + } - return new SOAP_Value('return',"{urn:$this->namespace}kt_response", $response); + return new SOAP_Value('return',"{urn:$this->namespace}$responseType", $response); } /** diff --git a/lib/documentmanagement/Document.inc b/lib/documentmanagement/Document.inc index ee629c3..b48a0c3 100644 --- a/lib/documentmanagement/Document.inc +++ b/lib/documentmanagement/Document.inc @@ -5,32 +5,32 @@ * KnowledgeTree Open Source Edition * Document Management Made Simple * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original - * copyright notice. + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. * Contributor( s): ______________________________________ */ @@ -107,6 +107,8 @@ class Document { function getRestoreFolderPath() { return $this->_oDocumentCore->getRestoreFolderPath(); } function setRestoreFolderPath($sValue) { $this->_oDocumentCore->setRestoreFolderPath($sValue); } + function getOemNo() { return $this->_oDocumentCore->getOemNo(); } + // Document Metadata Items @@ -610,6 +612,7 @@ class Document { function clearAllCaches() { + $GLOBALS["_OBJECTCACHE"]['Document'] = array(); KTEntityUtil::clearAllCaches('KTDocumentCore'); KTEntityUtil::clearAllCaches('KTDocumentContentVersion'); KTEntityUtil::clearAllCaches('KTDocumentMetadataVersion'); diff --git a/lib/documentmanagement/documentcore.inc.php b/lib/documentmanagement/documentcore.inc.php index 9fea43d..c619387 100644 --- a/lib/documentmanagement/documentcore.inc.php +++ b/lib/documentmanagement/documentcore.inc.php @@ -82,6 +82,8 @@ class KTDocumentCore extends KTEntity { var $dCheckedOut; + var $sOemNo; + var $_aFieldToSelect = array( "iId" => "id", @@ -114,10 +116,11 @@ class KTDocumentCore extends KTEntity { 'iRestoreFolderId' => 'restore_folder_id', 'sRestoreFolderPath' => 'restore_folder_path', - 'dCheckedOut'=>'checkedout' + 'dCheckedOut'=>'checkedout', + 'sOemNo'=>'oem_no' ); - function KTDocument() { + function KTDocumentCore() { } // {{{ getters/setters @@ -133,6 +136,8 @@ class KTDocumentCore extends KTEntity { function getCheckedOutDate() { return $this->dCheckedOut; } function setCheckedOutDate($dNewValue) { $this->dCheckedOut = $dNewValue; } + function getOemNo() { return $this->sOemNo; } + function getFolderId() { return $this->iFolderId; } function setFolderId($iNewValue) { $this->iFolderId = $iNewValue; } diff --git a/lib/documentmanagement/documentmetadataversion.inc.php b/lib/documentmanagement/documentmetadataversion.inc.php index f55766e..e8cf86c 100644 --- a/lib/documentmanagement/documentmetadataversion.inc.php +++ b/lib/documentmanagement/documentmetadataversion.inc.php @@ -5,32 +5,32 @@ * KnowledgeTree Open Source Edition * Document Management Made Simple * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original - * copyright notice. + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. * Contributor( s): ______________________________________ * */ @@ -103,9 +103,9 @@ class KTDocumentMetadataVersion extends KTEntity { function getDocumentTypeId() { return $this->iDocumentTypeId; } function setDocumentTypeId($iNewValue) { $this->iDocumentTypeId = $iNewValue; } function getName() { return sanitizeForSQLtoHTML($this->sName); } - function setName($sNewValue) { $this->sName = sanitizeForSQL($sNewValue); } + function setName($sNewValue) { $this->sName = $sNewValue; } function getDescription() { return sanitizeForSQLtoHTML($this->sDescription); } - function setDescription($sNewValue) { $this->sDescription = sanitizeForSQL($sNewValue); } + function setDescription($sNewValue) { $this->sDescription = $sNewValue; } function getStatusId() { return $this->iStatusId; } function setStatusId($iNewValue) { $this->iStatusId = $iNewValue; } function getVersionCreated() { return $this->dVersionCreated; } diff --git a/lib/foldermanagement/Folder.inc b/lib/foldermanagement/Folder.inc index 7d53bd6..fd18769 100644 --- a/lib/foldermanagement/Folder.inc +++ b/lib/foldermanagement/Folder.inc @@ -494,6 +494,7 @@ class Folder extends KTEntity { } function clearAllCaches() { + $GLOBALS["_OBJECTCACHE"]['Folder'] = array(); return KTEntityUtil::clearAllCaches('Folder'); } diff --git a/lib/help/helpreplacement.inc.php b/lib/help/helpreplacement.inc.php index 1098685..4ce1908 100644 --- a/lib/help/helpreplacement.inc.php +++ b/lib/help/helpreplacement.inc.php @@ -5,32 +5,32 @@ * KnowledgeTree Open Source Edition * Document Management Made Simple * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original - * copyright notice. + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. * Contributor( s): ______________________________________ * */ @@ -61,9 +61,9 @@ class KTHelpReplacement extends KTEntity { function getDescription() { return sanitizeForSQLtoHTML($this->sDescription); } function getTitle() { return sanitizeForSQLtoHTML($this->sTitle); } function setID($iId) { $this->iId = $iId; } - function setName($sName) { $this->sName = sanitizeForSQL($sName); } - function setDescription($sDescription) { $this->sDescription = sanitizeForSQL($sDescription); } - function setTitle($sTitle) { $this->sTitle= sanitizeForSQL($sTitle); } + function setName($sName) { $this->sName = $sName; } + function setDescription($sDescription) { $this->sDescription = $sDescription; } + function setTitle($sTitle) { $this->sTitle= $sTitle; } function _table () { global $default; diff --git a/lib/import/zipimportstorage.inc.php b/lib/import/zipimportstorage.inc.php index 7844cc0..073f356 100644 --- a/lib/import/zipimportstorage.inc.php +++ b/lib/import/zipimportstorage.inc.php @@ -7,71 +7,140 @@ * KnowledgeTree Open Source Edition * Document Management Made Simple * Copyright (C) 2004 - 2007 The Jam Warehouse Software (Pty) Limited - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License version 3 as published by the * Free Software Foundation. - * + * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. - * + * * The interactive user interfaces in modified source and object code versions * of this program must display Appropriate Legal Notices, as required under * Section 5 of the GNU General Public License version 3. - * + * * In accordance with Section 7(b) of the GNU General Public License version 3, * these Appropriate Legal Notices must retain the display of the "Powered by - * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * KnowledgeTree" logo and retain the original copyright notice. If the display of the * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices - * must display the words "Powered by KnowledgeTree" and retain the original - * copyright notice. + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. * Contributor( s): ______________________________________ */ require_once(KT_LIB_DIR . '/filelike/fsfilelike.inc.php'); require_once(KT_LIB_DIR . '/import/fsimportstorage.inc.php'); +require_once('File/Archive.php'); + class KTZipImportStorage extends KTFSImportStorage { - function KTZipImportStorage($sZipPath) { - $this->sZipPath = $sZipPath; + + /** + * The archive extension. + * @var string + */ + var $sExtension = 'zip'; + + var $sZipPath = ''; + + var $sBasePath = ''; + + var $aFile = array(); + + var $allowed_extensions = array('tgz', 'tar', 'gz', 'gzip', 'zip', 'deb', 'ar'); + + function KTZipImportStorage($sFilesName) { + $this->aFile = $_FILES[$sFilesName]; + $this->sZipPath = $this->aFile['tmp_name']; + + // Check the bzip2 lib functions are available + if(function_exists('bzopen')){ + $this->allowed_extensions = array_merge($this->allowed_extensions, array('bz2', 'bzip2', 'tbz')); + } + } + + function CheckFormat(){ + // Get the file extension + $aFilename = explode('.', $this->aFile['name']); + $cnt = count($aFilename); + $sExtension = $aFilename[$cnt - 1]; + + // check if its in the list of supported extensions + if(!in_array($sExtension, $this->allowed_extensions)){ + return false; + } + + $this->sExtension = (!empty($sExtension)) ? $sExtension : 'zip'; + + // Check if the archive is a .tar.gz or .tar.bz, etc + if($cnt > 2){ + if($aFilename[$cnt-2] == 'tar'){ + switch($this->sExtension){ + case 'gz': + $this->sExtension = 'tgz'; + break; + case 'bz2': + $this->sExtension = 'tbz'; + break; + } + } + } + + return true; + } + + function getFormats(){ + return implode(', ', $this->allowed_extensions); } function init() { $oKTConfig =& KTConfig::getSingleton(); - $sBasedir = $oKTConfig->get("urls/tmpDirectory"); - - $sTmpPath = tempnam($sBasedir, 'zipimportstorage'); + $sBasedir = $oKTConfig->get("urls/tmpDirectory"); + + $sTmpPath = tempnam($sBasedir, 'archiveimportstorage'); if ($sTmpPath === false) { - return PEAR::raiseError(_kt("Could not create temporary directory for zip storage")); + return PEAR::raiseError(_kt("Could not create temporary directory for archive storage")); } if (!file_exists($this->sZipPath)) { - return PEAR::raiseError(_kt("Zip file given does not exist")); + return PEAR::raiseError(_kt("Archive file given does not exist")); } unlink($sTmpPath); mkdir($sTmpPath, 0700); $this->sBasePath = $sTmpPath; - $sUnzipCommand = KTUtil::findCommand("import/unzip", "unzip"); - if (empty($sUnzipCommand)) { - return PEAR::raiseError(_kt("unzip command not found on system")); - } - $aArgs = array( - $sUnzipCommand, - "-q", "-n", - "-d", $sTmpPath, - $this->sZipPath, - ); - $aRes = KTUtil::pexec($aArgs); - - if ($aRes['ret'] !== 0) { - return PEAR::raiseError(_kt("Could not retrieve contents from zip storage")); + + // File Archive doesn't unzip properly so sticking to the original unzip functionality + if($this->sExtension == 'zip'){ + // ** Original zip functionality + $sUnzipCommand = KTUtil::findCommand("import/unzip", "unzip"); + if (empty($sUnzipCommand)) { + return PEAR::raiseError(_kt("unzip command not found on system")); + } + $aArgs = array( + $sUnzipCommand, + "-q", "-n", + "-d", $sTmpPath, + $this->sZipPath, + ); + $aRes = KTUtil::pexec($aArgs); + + if ($aRes['ret'] !== 0) { + return PEAR::raiseError(_kt("Could not retrieve contents from zip storage")); + } + }else{ + File_Archive::extract( + File_Archive::readArchive( + $this->sExtension, File_Archive::readUploadedFile('file') + ), + $dst = $sTmpPath + ); } } @@ -83,4 +152,4 @@ class KTZipImportStorage extends KTFSImportStorage { } } -?> +?> \ No newline at end of file diff --git a/lib/permissions/permissionutil.inc.php b/lib/permissions/permissionutil.inc.php index 40aa491..3a206d2 100644 --- a/lib/permissions/permissionutil.inc.php +++ b/lib/permissions/permissionutil.inc.php @@ -647,6 +647,9 @@ class KTPermissionUtil { */ function inheritPermissionObject(&$oDocumentOrFolder, $aOptions = null) { global $default; + + $oDocumentOrFolder->cacheGlobal=array(); + $bEvenIfNotOwner = KTUtil::arrayGet($aOptions, 'evenifnotowner'); if (empty($bEvenIfNotOwner) && !KTPermissionUtil::isPermissionOwner($oDocumentOrFolder)) { return PEAR::raiseError(_kt("Document or Folder doesn't own its permission object")); diff --git a/plugins/housekeeper/HouseKeeperPlugin.php b/plugins/housekeeper/HouseKeeperPlugin.php index 1baae44..9f5e671 100644 --- a/plugins/housekeeper/HouseKeeperPlugin.php +++ b/plugins/housekeeper/HouseKeeperPlugin.php @@ -35,6 +35,9 @@ * Contributor( s): ______________________________________ */ +require_once(KT_LIB_DIR . '/plugins/plugin.inc.php'); +require_once(KT_LIB_DIR . '/plugins/pluginregistry.inc.php'); + class HouseKeeperPlugin extends KTPlugin { var $autoRegister = true; @@ -49,8 +52,16 @@ class HouseKeeperPlugin extends KTPlugin $this->sFriendlyName = _kt('Housekeeper'); $config = KTConfig::getSingleton(); - $tempDir = $config->get('urls/tmpDirectory'); $cacheDir = $config->get('cache/cacheDirectory'); + $cacheFile = $cacheDir . '/houseKeeper.folders'; + + if (is_file($cacheFile)) + { + $this->folders = unserialize(file_get_contents($cacheFile)); + return; + } + + $tempDir = $config->get('urls/tmpDirectory'); $logDir = $config->get('urls/logDirectory'); $docsDir = $config->get('urls/documentRoot'); @@ -107,8 +118,13 @@ class HouseKeeperPlugin extends KTPlugin 'pattern'=>'', 'canClean'=>false ); + + // lets only cache this once it has been resolved! + file_put_contents($cacheFile, serialize($this->folders)); } + + } function getDirectories() diff --git a/plugins/ktcore/folder/BulkUpload.php b/plugins/ktcore/folder/BulkUpload.php index 18839d5..e95dd6f 100644 --- a/plugins/ktcore/folder/BulkUpload.php +++ b/plugins/ktcore/folder/BulkUpload.php @@ -115,16 +115,6 @@ class KTBulkUploadFolderAction extends KTFolderAction { unset($aErrorOptions['message']); $aFile = $this->oValidator->validateFile($_FILES['file'], $aErrorOptions); - // Ensure file is a zip file - $sMime = $aFile['type']; - $pos = strpos($sMime, 'x-zip-compressed'); - $pos2 = strpos($sMime, 'application/zip'); - if($pos === false && $pos2 === false){ - $this->addErrorMessage(_kt("Bulk Upload failed: File is not a zip file.")); - controllerRedirect("browse", 'fFolderId=' . $this->oFolder->getID()); - exit(0); - } - $matches = array(); $aFields = array(); foreach ($_REQUEST as $k => $v) { @@ -138,7 +128,14 @@ class KTBulkUploadFolderAction extends KTFolderAction { 'metadata' => $aFields, ); - $fs =& new KTZipImportStorage($aFile['tmp_name']); + $fs =& new KTZipImportStorage('file'); + if(!$fs->CheckFormat()){ + $sFormats = $fs->getFormats(); + $this->addErrorMessage(_kt("Bulk Upload failed. Archive is not an accepted format. Accepted formats are: ".$sFormats)); + controllerRedirect("browse", 'fFolderId=' . $this->oFolder->getID()); + exit; + } + $bm =& new KTBulkImportManager($this->oFolder, $fs, $this->oUser, $aOptions); $this->startTransaction(); $res = $bm->import(); @@ -152,3 +149,4 @@ class KTBulkUploadFolderAction extends KTFolderAction { exit(0); } } +?> \ No newline at end of file diff --git a/plugins/ktstandard/KTSubscriptions.php b/plugins/ktstandard/KTSubscriptions.php index ca43cbd..3d154e9 100644 --- a/plugins/ktstandard/KTSubscriptions.php +++ b/plugins/ktstandard/KTSubscriptions.php @@ -267,7 +267,7 @@ class KTDeleteSubscriptionTrigger { // fire subscription alerts for the checked in document $oSubscriptionEvent = new SubscriptionEvent(); $oFolder = Folder::get($oDocument->getFolderID()); - $oSubscriptionEvent->RemoveDocument($oDocument, $oFolder); + // $oSubscriptionEvent->RemoveDocument($oDocument, $oFolder); } } // }}} diff --git a/resources/css/errors.css b/resources/css/errors.css index f5da2d6..e557b0c 100644 --- a/resources/css/errors.css +++ b/resources/css/errors.css @@ -1,11 +1,14 @@ div#error-container { - width: 500px; + border:1px solid gray; color: #555; font-size: 11px; font-family: Verdana, Arial, sans-serif; + margin:2em auto; + padding:10px; + width:470px; } div#error-container div { - height: 140px; + height: 150px; } div#error-container h1 { font-weight: lighter; diff --git a/resources/js/loader.js b/resources/js/loader.js index 2198d2f..60dd45d 100644 --- a/resources/js/loader.js +++ b/resources/js/loader.js @@ -30,8 +30,10 @@ window.onload = function() } window.onsubmit = function(){ - var myElem = document.getElementById("modalDiv"); - myElem.style.display = "block"; + if(typeof disable_loader == "undefined"){ + var myElem = document.getElementById("modalDiv"); + myElem.style.display = "block"; + } } function Loader() { diff --git a/search2/indexing/indexerCore.inc.php b/search2/indexing/indexerCore.inc.php index e27772c..3450f05 100644 --- a/search2/indexing/indexerCore.inc.php +++ b/search2/indexing/indexerCore.inc.php @@ -74,6 +74,7 @@ class QueryResultItem protected $documentType; protected $mimeIconPath; protected $mimeDisplay; + protected $oemDocumentNo; public function __construct($document_id, $rank=null, $title=null, $text=null) { @@ -108,7 +109,7 @@ class QueryResultItem dcv.minor_version, dcv.filename, cou.name as checkoutuser, w.human_name as workflow, ws.human_name as workflowstate, mt.mimetypes as mimetype, md.mime_doc as mimedoc, d.checkedout, mbu.name as modifiedbyuser, d.modified, cbu.name as createdbyuser, ou.name as owneruser, d.immutable, d.status_id, d.created,dcv.storage_path, dtl.name as document_type, - mt.icon_path as mime_icon_path, mt.friendly_name as mime_display + mt.icon_path as mime_icon_path, mt.friendly_name as mime_display, d.oem_no FROM documents d INNER JOIN document_metadata_version dmv ON d.metadata_version_id = dmv.id @@ -168,6 +169,9 @@ class QueryResultItem $this->workflow = $result['workflow']; $this->workflowState = $result['workflowstate']; + $this->oemDocumentNo = $result['oem_no']; + if (empty($this->oemDocumentNo)) $this->oemDocumentNo = 'n/a'; + if (is_null($result['name'])) { $this->fullpath = '(orphaned)'; @@ -202,6 +206,7 @@ class QueryResultItem case 'Version': return (string) $this->version; case 'Filename': return (string)$this->filename; case 'FolderId': return (int)$this->folderId; + case 'OemDocumentNo': return (string) $this->oemDocumentNo; case 'Document': if (is_null($this->document)) { diff --git a/search2/search/fields/DocumentOemNoField.inc.php b/search2/search/fields/DocumentOemNoField.inc.php new file mode 100644 index 0000000..f208842 --- /dev/null +++ b/search2/search/fields/DocumentOemNoField.inc.php @@ -0,0 +1,58 @@ +. + * + * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place, + * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com. + * + * The interactive user interfaces in modified source and object code versions + * of this program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU General Public License version 3. + * + * In accordance with Section 7(b) of the GNU General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "Powered by + * KnowledgeTree" logo and retain the original copyright notice. If the display of the + * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices + * must display the words "Powered by KnowledgeTree" and retain the original + * copyright notice. + * Contributor( s): ______________________________________ + * + */ + +class DocumentOemNoField extends DBFieldExpr +{ + public function __construct() + { + parent::__construct('oem_no', 'documents', _kt('Integration Id')); + $this->setAlias('IntegrationId'); + } + + public function getInputRequirements() + { + return array('value'=>array('type'=>FieldInputType::INT )); + } + + public function is_valid() + { + return DefaultOpCollection::validateParent($this, DefaultOpCollection::$is); + } +} + +?> \ No newline at end of file diff --git a/search2/search/search.inc.php b/search2/search/search.inc.php index 8822599..bc3b19d 100644 --- a/search2/search/search.inc.php +++ b/search2/search/search.inc.php @@ -556,7 +556,7 @@ function processSearchExpression($query) 'document_id' => (int) $hit->DocumentID, 'custom_document_no' => 'n/a', - 'oem_document_no' => 'n/a', + 'oem_document_no' => (string) $hit->OemDocumentNo, 'relevance' => (float) $hit->Rank, 'text' => (string) $noText?'':$hit->Text, diff --git a/sql/mysql/install/structure.sql b/sql/mysql/install/structure.sql index 5673bdd..d5735f2 100644 --- a/sql/mysql/install/structure.sql +++ b/sql/mysql/install/structure.sql @@ -557,6 +557,7 @@ CREATE TABLE `documents` ( `restore_folder_id` int(11) default NULL, `restore_folder_path` text, `checkedout` datetime default NULL, + `oem_no` varchar(255) default NULL, PRIMARY KEY (`id`), KEY `creator_id` (`creator_id`), KEY `folder_id` (`folder_id`), @@ -571,6 +572,7 @@ CREATE TABLE `documents` ( KEY `full_path` (`full_path`(255)), KEY `immutable` (`immutable`), KEY `checkedout` (`checkedout`), + KEY `oem_no` (`oem_no`), CONSTRAINT `documents_ibfk_1` FOREIGN KEY (`creator_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE SET NULL, CONSTRAINT `documents_ibfk_2` FOREIGN KEY (`folder_id`) REFERENCES `folders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `documents_ibfk_3` FOREIGN KEY (`checked_out_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE SET NULL, diff --git a/sql/mysql/upgrade/3.5.2/oem_no.sql b/sql/mysql/upgrade/3.5.2/oem_no.sql new file mode 100644 index 0000000..74462d6 --- /dev/null +++ b/sql/mysql/upgrade/3.5.2/oem_no.sql @@ -0,0 +1 @@ +ALTER TABLE documents ADD oem_no varchar(255) NULL, ADD INDEX (oem_no); \ No newline at end of file diff --git a/templates/ktstandard/PDFPlugin/PDFPlugin.smarty b/templates/ktstandard/PDFPlugin/PDFPlugin.smarty index c95a5db..2ff65b2 100644 --- a/templates/ktstandard/PDFPlugin/PDFPlugin.smarty +++ b/templates/ktstandard/PDFPlugin/PDFPlugin.smarty @@ -1,3 +1,9 @@ +{literal} + +{/literal} +

get("ui/morphTo")}/title_bullet.png{else}{$rootUrl}/resources/graphics/title_bullet.png{/if}"/>{i18n}Generate PDF of{/i18n}:
{$context->oDocument->getName()|sanitize}

{$form->render()} diff --git a/thirdparty/pear/File/Archive.php b/thirdparty/pear/File/Archive.php new file mode 100644 index 0000000..b3a5f95 --- /dev/null +++ b/thirdparty/pear/File/Archive.php @@ -0,0 +1,1403 @@ + + * @copyright 1997-2005 The PHP Group + * @license http://www.gnu.org/copyleft/lesser.html LGPL + * @version CVS: $Id: Archive.php,v 1.85 2005/08/16 08:48:59 vincentlascaux Exp $ + * @link http://pear.php.net/package/File_Archive + */ + +/** + * To have access to PEAR::isError and PEAR::raiseError + * We should probably use lazy include and remove this inclusion... + */ +require_once "PEAR.php"; + +function File_Archive_cleanCache($file, $group) +{ + $file = split('_', $file); + if (count($file) != 3) { + return false; //not a File_Archive file, keep it + } + + $name = $file[2]; + $name = urldecode($name); + + $group = $file[1]; + + //clean the cache only for files in File_Archive groups + return substr($group, 0, 11) == 'FileArchive' && + !file_exists($name); //and only if the related file no longer exists +} + +/** + * Factory to access the most common File_Archive features + * It uses lazy include, so you dont have to include the files from + * File/Archive/* directories + */ +class File_Archive +{ + function& _option($name) + { + static $container = array( + 'zipCompressionLevel' => 9, + 'gzCompressionLevel' => 9, + 'tmpDirectory' => '.', + 'cache' => null, + 'appendRemoveDuplicates' => false, + 'blockSize' => 65536, + 'cacheCondition' => false + ); + return $container[$name]; + } + /** + * Sets an option that will be used by default by all readers or writers + * Option names are case sensitive + * Currently, the following options are used: + * + * "cache" + * Instance of a Cache_Lite object used to cache some compressed + * data to speed up future compressions of files + * Default: null (no cache used) + * + * "zipCompressionLevel" + * Value between 0 and 9 specifying the default compression level used + * by Zip writers (0 no compression, 9 highest compression) + * Default: 9 + * + * "gzCompressionLevel" + * Value between 0 and 9 specifying the default compression level used + * by Gz writers (0 no compression, 9 highest compression) + * Default: 9 + * + * "tmpDirectory" + * Directory where the temporary files generated by File_Archive will + * be created + * Default: '.' + * + * "appendRemoveDuplicates" + * If set to true, the appender created will by default remove the + * file present in the archive when adding a new one. This will slow the + * appending of files to archives + * Default: false + * + * "blockSize" + * To transfer data from a reader to a writer, some chunks a read from the + * source and written to the writer. This parameter controls the size of the + * chunks + * Default: 64kB + * + * "cacheCondition" + * This parameter specifies when a cache should be used. When the cache is + * used, the data of the reader is saved in a temporary file for future access. + * The cached reader will be read only once, even if you read it several times. + * This can be usefull to read compressed files or downloaded files (from http or ftp) + * The possible values for this option are + * - false: never use cache + * - a regexp: A cache will be used if the specified URL matches the regexp + * preg_match is used + * Default: false + * Example: '/^(http|ftp):\/\//' will cache all files downloaded via http or ftp + * + */ + function setOption($name, $value) + { + $option =& File_Archive::_option($name); + $option = $value; + if ($name == 'cache' && $value !== null) { + //TODO: ask to Cache_Lite to allow that + $value->_fileNameProtection = false; + } + } + + /** + * Retrieve the value of an option + */ + function getOption($name) + { + return File_Archive::_option($name); + } + + /** + * Create a reader to read the URL $URL. + * If the URL is a directory, it will recursively read that directory. + * If $uncompressionLevel is not null, the archives (files with extension + * tar, zip, gz or tgz) will be considered as directories (up to a depth of + * $uncompressionLevel if $uncompressionLevel > 0). The reader will only + * read files with a directory depth of $directoryDepth. It reader will + * replace the given URL ($URL) with $symbolic in the public filenames + * The default symbolic name is the last filename in the URL (or '' for + * directories) + * + * Examples: + * Considere the following file system + *
+     * a.txt
+     * b.tar (archive that contains the following files)
+     *     c.txt
+     *     d.tgz (archive that contains the following files)
+     *         e.txt
+     *         dir1/
+     *             f.txt
+     * dir2/
+     *     g.txt
+     *     dir3/
+     *         h.tar (archive that contains the following files)
+     *             i.txt
+     * 
+ * + * read('.') will return a reader that gives access to following + * files (recursively read current dir): + *
+     * a.txt
+     * b.tar
+     * dir2/g.txt
+     * dir2/dir3/h.tar
+     * 
+ * + * read('.', 'myBaseDir') will return the following reader: + *
+     * myBaseDir/a.txt
+     * myBaseDir/b.tar
+     * myBaseDir/dir2/g.txt
+     * myBaseDir/dir2/dir3/h.tar
+     * 
+ * + * read('.', '', -1) will return the following reader (uncompress + * everything) + *
+     * a.txt
+     * b.tar/c.txt
+     * b.tar/d.tgz/e.txt
+     * b.tar/d.tgz/dir1/f.txt
+     * dir2/g.txt
+     * dir2/dir3/h.tar/i.txt
+     * 
+ * + * read('.', '', 1) will uncompress only one level (so d.tgz will + * not be uncompressed): + *
+     * a.txt
+     * b.tar/c.txt
+     * b.tar/d.tgz
+     * dir2/g.txt
+     * dir2/dir3/h.tar/i.txt
+     * 
+ * + * read('.', '', 0, 0) will not recurse into subdirectories + *
+     * a.txt
+     * b.tar
+     * 
+ * + * read('.', '', 0, 1) will recurse only one level in + * subdirectories + *
+     * a.txt
+     * b.tar
+     * dir2/g.txt
+     * 
+ * + * read('.', '', -1, 2) will uncompress everything and recurse in + * only 2 levels in subdirectories or archives + *
+     * a.txt
+     * b.tar/c.txt
+     * b.tar/d.tgz/e.txt
+     * dir2/g.txt
+     * 
+ * + * The recursion level is determined by the real path, not the symbolic one. + * So read('.', 'myBaseDir', -1, 2) will result to the same files: + *
+     * myBaseDir/a.txt
+     * myBaseDir/b.tar/c.txt
+     * myBaseDir/b.tar/d.tgz/e.txt (accepted because the real depth is 2)
+     * myBaseDir/dir2/g.txt
+     * 
+ * + * Use readSource to do the same thing, reading from a specified reader instead of + * reading from the system files + * + * To read a single file, you can do read('a.txt', 'public_name.txt') + * If no public name is provided, the default one is the name of the file + * read('dir2/g.txt') contains the single file named 'g.txt' + * read('b.tar/c.txt') contains the single file named 'c.txt' + * + * Note: This function uncompress files reading their extension + * The compressed files must have a tar, zip, gz or tgz extension + * Since it is impossible for some URLs to use is_dir or is_file, this + * function may not work with + * URLs containing folders which name ends with such an extension + */ + function readSource(&$source, $URL, $symbolic = null, + $uncompression = 0, $directoryDepth = -1) + { + return File_Archive::_readSource($source, $URL, $reachable, $baseDir, + $symbolic, $uncompression, $directoryDepth); + } + + /** + * This function performs exactly as readSource, but with two additional parameters + * ($reachable and $baseDir) that will be set so that $reachable."/".$baseDir == $URL + * and $reachable can be reached (in case of error) + * + * @access private + */ + function _readSource(&$toConvert, $URL, &$reachable, &$baseDir, $symbolic = null, + $uncompression = 0, $directoryDepth = -1) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + if (is_array($URL)) { + $converted = array(); + foreach($URL as $key => $foo) { + $converted[] =& File_Archive::_convertToReader($URL[$key]); + } + return File_Archive::readMulti($converted); + } + + //No need to uncompress more than $directoryDepth + //That's not perfect, and some archives will still be uncompressed just + //to be filtered out :( + if ($directoryDepth >= 0) { + $uncompressionLevel = min($uncompression, $directoryDepth); + } else { + $uncompressionLevel = $uncompression; + } + + require_once 'File/Archive/Reader.php'; + $std = File_Archive_Reader::getStandardURL($URL); + + //Modify the symbolic name if necessary + $slashPos = strrpos($std, '/'); + if ($symbolic === null) { + if ($slashPos === false) { + $realSymbolic = $std; + } else { + $realSymbolic = substr($std, $slashPos+1); + } + } else { + $realSymbolic = $symbolic; + } + if ($slashPos !== false) { + $baseFile = substr($std, 0, $slashPos+1); + $lastFile = substr($std, $slashPos+1); + } else { + $baseFile = ''; + $lastFile = $std; + } + + if (strpos($lastFile, '*')!==false || + strpos($lastFile, '?')!==false) { + //We have to build a regexp here + $regexp = str_replace( + array('\*', '\?'), + array('[^/]*', '[^/]'), + preg_quote($lastFile) + ); + $result = File_Archive::_readSource($source, $baseFile, + $reachable, $baseDir, null, 0, -1); + return File_Archive::filter( + File_Archive::predEreg('^'.$regexp.'$'), + $result + ); + } + + //If the URL can be interpreted as a directory, and we are reading from the file system + if ((empty($URL) || is_dir($URL)) && $source === null) { + require_once "File/Archive/Reader/Directory.php"; + require_once "File/Archive/Reader/ChangeName.php"; + + if ($uncompressionLevel != 0) { + require_once "File/Archive/Reader/Uncompress.php"; + $result = new File_Archive_Reader_Uncompress( + new File_Archive_Reader_Directory($std, '', $directoryDepth), + $uncompressionLevel + ); + } else { + $result = new File_Archive_Reader_Directory($std, '', $directoryDepth); + } + + if ($directoryDepth >= 0) { + require_once 'File/Archive/Reader/Filter.php'; + require_once 'File/Archive/Predicate/MaxDepth.php'; + + $tmp =& File_Archive::filter( + new File_Archive_Predicate_MaxDepth($directoryDepth), + $result + ); + unset($result); + $result =& $tmp; + } + if (!empty($realSymbolic)) { + if ($symbolic === null) { + $realSymbolic = ''; + } + $tmp =& new File_Archive_Reader_AddBaseName( + $realSymbolic, + $result + ); + unset($result); + $result =& $tmp; + } + + //If the URL can be interpreted as a file, and we are reading from the file system + } else if (is_file($URL) && substr($URL, -1)!='/' && $source === null) { + require_once "File/Archive/Reader/File.php"; + $result = new File_Archive_Reader_File($URL, $realSymbolic); + + //Else, we will have to build a complex reader + } else { + require_once "File/Archive/Reader/File.php"; + + $realPath = $std; + + // Try to find a file with a known extension in the path ( + // (to manage URLs like archive.tar/directory/file) + $pos = 0; + do { + if ($pos+1setBaseDir($std); + if (PEAR::isError($isDir)) { + return $isDir; + } + if ($isDir && $symbolic==null) { + //Default symbolic name for directories is empty + $realSymbolic = ''; + } + + if ($directoryDepth >= 0) { + //Limit the maximum depth if necessary + require_once "File/Archive/Predicate/MaxDepth.php"; + + $tmp = new File_Archive_Reader_Filter( + new File_Archive_Predicate( + $directoryDepth + + substr_count(substr($std, $pos+1), '/') + ), + $result + ); + unset($result); + $result =& $tmp; + } + + if ($std != $realSymbolic) { + require_once "File/Archive/Reader/ChangeName.php"; + + //Change the base name to the symbolic one if necessary + $tmp = new File_Archive_Reader_ChangeBaseName( + $std, + $realSymbolic, + $result + ); + unset($result); + $result =& $tmp; + } + } + + $cacheCondition = File_Archive::getOption('cacheCondition'); + if ($cacheCondition !== false && + preg_match($cacheCondition, $URL)) { + $tmp =& File_Archive::cache($result); + unset($result); + $result =& $tmp; + } + + return $result; + } + function read($URL, $symbolic = null, + $uncompression = 0, $directoryDepth = -1) + { + $source = null; + return File_Archive::readSource($source, $URL, $symbolic, $uncompression, $directoryDepth); + } + + /** + * Create a file reader on an uploaded file. The reader will read + * $_FILES[$name]['tmp_name'] and will have $_FILES[$name]['name'] + * as a symbolic filename. + * + * A PEAR error is returned if one of the following happen + * - $_FILES[$name] is not set + * - $_FILES[$name]['error'] is not 0 + * - is_uploaded_file returns false + * + * @param string $name Index of the file in the $_FILES array + * @return File_Archive_Reader File reader on the uploaded file + */ + function readUploadedFile($name) + { + if (!isset($_FILES[$name])) { + return PEAR::raiseError("File $name has not been uploaded"); + } + switch ($_FILES[$name]['error']) { + case 0: + //No error + break; + case 1: + return PEAR::raiseError( + "The upload size limit didn't allow to upload file ". + $_FILES[$name]['name'] + ); + case 2: + return PEAR::raiseError( + "The form size limit didn't allow to upload file ". + $_FILES[$name]['name'] + ); + case 3: + return PEAR::raiseError( + "The file was not entirely uploaded" + ); + case 4: + return PEAR::raiseError( + "The uploaded file is empty" + ); + default: + return PEAR::raiseError( + "Unknown error ".$_FILES[$name]['error']." in file upload. ". + "Please, report a bug" + ); + } + if (!is_uploaded_file($_FILES[$name]['tmp_name'])) { + return PEAR::raiseError("The file is not an uploaded file"); + } + + require_once "File/Archive/Reader/File.php"; + return new File_Archive_Reader_File( + $_FILES[$name]['tmp_name'], + $_FILES[$name]['name'], + $_FILES[$name]['type'] + ); + } + + /** + * Adds a cache layer above the specified reader + * The data of the reader is saved in a temporary file for future access. + * The cached reader will be read only once, even if you read it several times. + * This can be usefull to read compressed files or downloaded files (from http or ftp) + * + * @param mixed $toConvert The reader to cache + * It can be a File_Archive_Reader or a string, which will be converted using the + * read function + */ + function cache(&$toConvert) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + + require_once 'File/Archive/Reader/Cache.php'; + return new File_Archive_Reader_Cache($source); + } + + /** + * Try to interpret the object as a reader + * Strings are converted to readers using File_Archive::read + * Arrays are converted to readers using File_Archive::readMulti + * + * @access private + */ + function &_convertToReader(&$source) + { + if (is_string($source)) { + $cacheCondition = File_Archive::getOption('cacheCondition'); + if ($cacheCondition !== false && + preg_match($cacheCondition, $source)) { + return File_Archive::cache(File_Archive::read($source)); + } else { + return File_Archive::read($source); + } + } else if (is_array($source)) { + return File_Archive::readMulti($source); + } else { + return $source; + } + } + + /** + * Try to interpret the object as a writer + * Strings are converted to writers using File_Archive::appender + * Arrays are converted to writers using a multi writer + * + * @access private + */ + function &_convertToWriter(&$dest) + { + if (is_string($dest)) { + return File_Archive::appender($dest); + } else if (is_array($dest)) { + require_once 'File/Archive/Writer/Multi.php'; + $writer = new File_Archive_Writer_Multi(); + foreach($dest as $key => $foo) { + $writer->addWriter($dest[$key]); + } + } else { + return $dest; + } + } + + /** + * Check if a file with a specific extension can be read as an archive + * with File_Archive::read* + * This function is case sensitive. + * + * @param string $extension the checked extension + * @return bool whether this file can be understood reading its extension + * Currently, supported extensions are tar, zip, gz, tgz, tbz, bz2, + * bzip2, ar, deb + */ + function isKnownExtension($extension) + { + return $extension == 'tar' || + $extension == 'zip' || + $extension == 'gz' || + $extension == 'tgz' || + $extension == 'tbz' || + $extension == 'bz2' || + $extension == 'bzip2' || + $extension == 'ar' || + $extension == 'deb' /* || + $extension == 'cab' || + $extension == 'rar' */; + } + + /** + * Create a reader that will read the single file source $source as + * a specific archive + * + * @param string $extension determines the kind of archive $source contains + * $extension is case sensitive + * @param File_Archive_Reader $source stores the archive + * @param bool $sourceOpened specifies if the archive is already opened + * if false, next will be called on source + * Closing the returned archive will close $source iif $sourceOpened + * is true + * @return A File_Archive_Reader that uncompresses the archive contained in + * $source interpreting it as a $extension archive + * If $extension is not handled return false + */ + function readArchive($extension, &$toConvert, $sourceOpened = false) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + + switch($extension) { + case 'tgz': + return File_Archive::readArchive('tar', + File_Archive::readArchive('gz', $source, $sourceOpened) + ); + case 'tbz': + return File_Archive::readArchive('tar', + File_Archive::readArchive('bz2', $source, $sourceOpened) + ); + case 'tar': + require_once 'File/Archive/Reader/Tar.php'; + return new File_Archive_Reader_Tar($source, $sourceOpened); + + case 'gz': + case 'gzip': + require_once 'File/Archive/Reader/Gzip.php'; + return new File_Archive_Reader_Gzip($source, $sourceOpened); + + case 'zip': + require_once 'File/Archive/Reader/Zip.php'; + return new File_Archive_Reader_Zip($source, $sourceOpened); + + case 'bz2': + case 'bzip2': + require_once 'File/Archive/Reader/Bzip2.php'; + return new File_Archive_Reader_Bzip2($source, $sourceOpened); + + case 'deb': + case 'ar': + require_once 'File/Archive/Reader/Ar.php'; + return new File_Archive_Reader_Ar($source, $sourceOpened); + +/* case 'cab': + require_once 'File/Archive/Reader/Cab.php'; + return new File_Archive_Reader_Cab($source, $sourceOpened); + + + case 'rar': + require_once "File/Archive/Reader/Rar.php"; + return new File_Archive_Reader_Rar($source, $sourceOpened); */ + + default: + return false; + } + } + + /** + * Contains only one file with data read from a memory buffer + * + * @param string $memory content of the file + * @param string $filename public name of the file + * @param array $stat statistics of the file. Index 7 (size) will be + * overwritten to match the size of $memory + * @param string $mime mime type of the file. Default will determine the + * mime type thanks to the extension of $filename + * @see File_Archive_Reader_Memory + */ + function readMemory($memory, $filename, $stat=array(), $mime=null) + { + require_once "File/Archive/Reader/Memory.php"; + return new File_Archive_Reader_Memory($memory, $filename, $stat, $mime); + } + + /** + * Contains several other sources. Take care the sources don't have several + * files with the same filename. The sources are given as a parameter, or + * can be added thanks to the reader addSource method + * + * @param array $sources Array of strings or readers that will be added to + * the multi reader. If the parameter is a string, a reader will be + * built thanks to the read function + * @see File_Archive_Reader_Multi, File_Archive::read() + */ + function readMulti($sources = array()) + { + require_once "File/Archive/Reader/Multi.php"; + $result = new File_Archive_Reader_Multi(); + foreach ($sources as $index => $foo) { + $s =& File_Archive::_convertToReader($sources[$index]); + if (PEAR::isError($s)) { + return $s; + } else { + $result->addSource($s); + } + } + return $result; + } + /** + * Make the files of a source appear as one large file whose content is the + * concatenation of the content of all the files + * + * @param File_Archive_Reader $source The source whose files must be + * concatened + * @param string $filename name of the only file of the created reader + * @param array $stat statistics of the file. Index 7 (size) will be + * overwritten to match the total size of the files + * @param string $mime mime type of the file. Default will determine the + * mime type thanks to the extension of $filename + * @see File_Archive_Reader_Concat + */ + function readConcat(&$toConvert, $filename, $stat=array(), $mime=null) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + + require_once "File/Archive/Reader/Concat.php"; + return new File_Archive_Reader_Concat($source, $filename, $stat, $mime); + } + + /** + * Removes from a source the files that do not follow a given predicat + * + * @param File_Archive_Predicate $predicate Only the files for which + * $predicate->isTrue() will be kept + * @param File_Archive_Reader $source Source that will be filtered + * @see File_Archive_Reader_Filter + */ + function filter($predicate, &$toConvert) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + + require_once "File/Archive/Reader/Filter.php"; + return new File_Archive_Reader_Filter($predicate, $source); + } + /** + * Predicate that always evaluate to true + * + * @see File_Archive_Predicate_True + */ + function predTrue() + { + require_once "File/Archive/Predicate/True.php"; + return new File_Archive_Predicate_True(); + } + /** + * Predicate that always evaluate to false + * + * @see File_Archive_Predicate_False + */ + function predFalse() + { + require_once "File/Archive/Predicate/False.php"; + return new File_Archive_Predicate_False(); + } + /** + * Predicate that evaluates to the logical AND of the parameters + * You can add other predicates thanks to the + * File_Archive_Predicate_And::addPredicate() function + * + * @param File_Archive_Predicate (any number of them) + * @see File_Archive_Predicate_And + */ + function predAnd() + { + require_once "File/Archive/Predicate/And.php"; + $pred = new File_Archive_Predicate_And(); + $args = func_get_args(); + foreach ($args as $p) { + $pred->addPredicate($p); + } + return $pred; + } + /** + * Predicate that evaluates to the logical OR of the parameters + * You can add other predicates thanks to the + * File_Archive_Predicate_Or::addPredicate() function + * + * @param File_Archive_Predicate (any number of them) + * @see File_Archive_Predicate_Or + */ + function predOr() + { + require_once "File/Archive/Predicate/Or.php"; + $pred = new File_Archive_Predicate_Or(); + $args = func_get_args(); + foreach ($args as $p) { + $pred->addPredicate($p); + } + return $pred; + } + /** + * Negate a predicate + * + * @param File_Archive_Predicate $pred Predicate to negate + * @see File_Archive_Predicate_Not + */ + function predNot($pred) + { + require_once "File/Archive/Predicate/Not.php"; + return new File_Archive_Predicate_Not($pred); + } + /** + * Evaluates to true iif the file is larger than a given size + * + * @param int $size the minimal size of the files (in Bytes) + * @see File_Archive_Predicate_MinSize + */ + function predMinSize($size) + { + require_once "File/Archive/Predicate/MinSize.php"; + return new File_Archive_Predicate_MinSize($size); + } + /** + * Evaluates to true iif the file has been modified after a given time + * + * @param int $time Unix timestamp of the minimal modification time of the + * files + * @see File_Archive_Predicate_MinTime + */ + function predMinTime($time) + { + require_once "File/Archive/Predicate/MinTime.php"; + return new File_Archive_Predicate_MinTime($time); + } + /** + * Evaluates to true iif the file has less that a given number of + * directories in its path + * + * @param int $depth Maximal number of directories in path of the files + * @see File_Archive_Predicate_MaxDepth + */ + function predMaxDepth($depth) + { + require_once "File/Archive/Predicate/MaxDepth.php"; + return new File_Archive_Predicate_MaxDepth($depth); + } + /** + * Evaluates to true iif the extension of the file is in a given list + * + * @param array or string $list List or comma separated string of possible + * extension of the files + * @see File_Archive_Predicate_Extension + */ + function predExtension($list) + { + require_once "File/Archive/Predicate/Extension.php"; + return new File_Archive_Predicate_Extension($list); + } + /** + * Evaluates to true iif the MIME type of the file is in a given list + * + * @param array or string $list List or comma separated string of possible + * MIME types of the files. You may enter wildcards like "image/*" to + * select all the MIME in class image + * @see File_Archive_Predicate_MIME, MIME_Type::isWildcard() + */ + function predMIME($list) + { + require_once "File/Archive/Predicate/MIME.php"; + return new File_Archive_Predicate_MIME($list); + } + /** + * Evaluates to true iif the name of the file follow a given regular + * expression + * + * @param string $ereg regular expression that the filename must follow + * @see File_Archive_Predicate_Ereg, ereg() + */ + function predEreg($ereg) + { + require_once "File/Archive/Predicate/Ereg.php"; + return new File_Archive_Predicate_Ereg($ereg); + } + /** + * Evaluates to true iif the name of the file follow a given regular + * expression (case insensitive version) + * + * @param string $ereg regular expression that the filename must follow + * @see File_Archive_Predicate_Eregi, eregi + */ + function predEregi($ereg) + { + require_once "File/Archive/Predicate/Eregi.php"; + return new File_Archive_Predicate_Eregi($ereg); + } + /** + * Evaluates to true only after a given number of evaluations + * This can be used to select files by index since the evaluation is done + * once per file + * + * @param array The indexes for which the returned predicate will return true + * are the keys of the array + * The predicate will return true if isset($indexes[$pos]) + */ + function predIndex($indexes) + { + require_once "File/Archive/Predicate/Index.php"; + return new File_Archive_Predicate_Index($indexes); + } + /** + * Custom predicate built by supplying a string expression + * + * Here are different ways to create a predicate that keeps only files + * with names shorter than 100 chars + * + * File_Archive::predCustom("return strlen($name)<100;") + * File_Archive::predCustom("strlen($name)<100;") + * File_Archive::predCustom("strlen($name)<100") + * File_Archive::predCustom("strlen($source->getFilename())<100") + * + * + * @param string $expression String containing an expression that evaluates + * to a boolean. If the expression doesn't contain a return + * statement, it will be added at the begining of the expression + * A ';' will be added at the end of the expression so that you don't + * have to write it. You may use the $name variable to refer to the + * current filename (with path...), $time for the modification time + * (unix timestamp), $size for the size of the file in bytes, $mime + * for the MIME type of the file + * @see File_Archive_Predicate_Custom + */ + function predCustom($expression) + { + require_once "File/Archive/Predicate/Custom.php"; + return new File_Archive_Predicate_Custom($expression); + } + + /** + * Send the files as a mail attachment + * + * @param Mail $mail Object used to send mail (see Mail::factory) + * @param array or String $to An array or a string with comma separated + * recipients + * @param array $headers The headers that will be passed to the Mail_mime + * object + * @param string $message Text body of the mail + * @see File_Archive_Writer_Mail + */ + function toMail($to, $headers, $message, $mail = null) + { + require_once "File/Archive/Writer/Mail.php"; + return new File_Archive_Writer_Mail($to, $headers, $message, $mail); + } + /** + * Write the files on the hard drive + * + * @param string $baseDir if specified, the files will be created in that + * directory. If they don't exist, the directories will automatically + * be created + * @see File_Archive_Writer_Files + */ + function toFiles($baseDir = "") + { + require_once "File/Archive/Writer/Files.php"; + return new File_Archive_Writer_Files($baseDir); + } + /** + * Send the content of the files to a memory buffer + * + * toMemory returns a writer where the data will be written. + * In this case, the data is accessible using the getData member + * + * toVariable returns a writer that will write into the given + * variable + * + * @param out $data if specified, the data will be written to this buffer + * Else, you can retrieve the buffer with the + * File_Archive_Writer_Memory::getData() function + * @see File_Archive_Writer_Memory + */ + function toMemory() + { + $v = ''; + return File_Archive::toVariable($v); + } + function toVariable(&$v) + { + require_once "File/Archive/Writer/Memory.php"; + return new File_Archive_Writer_Memory($v); + } + /** + * Duplicate the writing operation on two writers + * + * @param File_Archive_Writer $a, $b writers where data will be duplicated + * @see File_Archive_Writer_Multi + */ + function toMulti(&$aC, &$bC) + { + $a =& File_Archive::_convertToWriter($aC); + $b =& File_Archive::_convertToWriter($bC); + + if (PEAR::isError($a)) { + return $a; + } + if (PEAR::isError($b)) { + return $b; + } + + require_once "File/Archive/Writer/Multi.php"; + $writer = new File_Archive_Writer_Multi(); + $writer->addWriter($a); + $writer->addWriter($b); + return $writer; + } + /** + * Send the content of the files to the standard output (so to the client + * for a website) + * + * @param bool $sendHeaders If true some headers will be sent to force the + * download of the file. Default value is true + * @see File_Archive_Writer_Output + */ + function toOutput($sendHeaders = true) + { + require_once "File/Archive/Writer/Output.php"; + return new File_Archive_Writer_Output($sendHeaders); + } + /** + * Compress the data to a tar, gz, tar/gz or zip format + * + * @param string $filename name of the archive file + * @param File_Archive_Writer $innerWriter writer where the archive will be + * written + * @param string $type can be one of tgz, tbz, tar, zip, gz, gzip, bz2, + * bzip2 (default is the extension of $filename) or any composition + * of them (for example tar.gz or tar.bz2). The case of this + * parameter is not important. + * @param array $stat Statistics of the archive (see stat function) + * @param bool $autoClose If set to true, $innerWriter will be closed when + * the returned archive is close. Default value is true. + */ + function toArchive($filename, &$toConvert, $type = null, + $stat = array(), $autoClose = true) + { + $innerWriter =& File_Archive::_convertToWriter($toConvert); + if (PEAR::isError($innerWriter)) { + return $innerWriter; + } + $shortcuts = array("tgz" , "tbz" ); + $reals = array("tar.gz", "tar.bz2"); + + if ($type === null) { + $extensions = strtolower($filename); + } else { + $extensions = strtolower($type); + } + $extensions = explode('.', str_replace($shortcuts, $reals, $extensions)); + if ($innerWriter !== null) { + $writer =& $innerWriter; + } else { + $writer = File_Archive::toFiles(); + } + $nbCompressions = 0; + $currentFilename = $filename; + while (($extension = array_pop($extensions)) !== null) { + unset($next); + switch($extension) { + case "tar": + require_once "File/Archive/Writer/Tar.php"; + $next = new File_Archive_Writer_Tar( + $currentFilename, $writer, $stat, $autoClose + ); + unset($writer); $writer =& $next; + break; + case "zip": + require_once "File/Archive/Writer/Zip.php"; + $next = new File_Archive_Writer_Zip( + $currentFilename, $writer, $stat, $autoClose + ); + unset($writer); $writer =& $next; + break; + case "gz": + case "gzip": + require_once "File/Archive/Writer/Gzip.php"; + $next = new File_Archive_Writer_Gzip( + $currentFilename, $writer, $stat, $autoClose + ); + unset($writer); $writer =& $next; + break; + case "bz2": + case "bzip2": + require_once "File/Archive/Writer/Bzip2.php"; + $next = new File_Archive_Writer_Bzip2( + $currentFilename, $writer, $stat, $autoClose + ); + unset($writer); $writer =& $next; + break; + case "deb": + case "ar": + require_once "File/Archive/Writer/Ar.php"; + $next = new File_Archive_Writer_Ar( + $currentFilename, $writer, $stat, $autoClose + ); + unset($writer); $writer =& $next; + break; + default: + if ($type !== null || $nbCompressions == 0) { + return PEAR::raiseError("Archive $extension unknown"); + } + break; + } + $nbCompressions ++; + $autoClose = true; + $currentFilename = implode(".", $extensions); + } + return $writer; + } + + + /** + * File_Archive::extract($source, $dest) is equivalent to $source->extract($dest) + * If $source is a PEAR error, the error will be returned + * It is thus easier to use this function than $source->extract, since it reduces the number of + * error checking and doesn't force you to define a variable $source + * + * You may use strings as source and dest. In that case the source is automatically + * converted to a reader using File_Archive::read and the dest is converted to a + * writer using File_Archive::appender + * Since PHP doesn't allow to pass literal strings by ref, you will have to use temporary + * variables. + * File_Archive::extract($src = 'archive.zip/', $dest = 'dir') will extract the archive to 'dir' + * It is the same as + * File_Archive::extract( + * File_Archive::read('archive.zip/'), + * File_Archive::appender('dir') + * ); + * You may use any variable in the extract function ($from/$to, $a/$b...). + * + * @param File_Archive_Reader $source The source that will be read + * @param File_Archive_Writer $dest Where to copy $source files + * @param bool $autoClose if true (default), $dest will be closed after the extraction + * @param int $bufferSize Size of the buffer to use to move data from the reader to the buffer + * If $bufferSize <= 0 (default), the blockSize option is used + * You shouldn't need to change that + * @return null or a PEAR error if an error occured + */ + function extract(&$sourceToConvert, &$destToConvert, $autoClose = true, $bufferSize = 0) + { + $source =& File_Archive::_convertToReader($sourceToConvert); + if (PEAR::isError($source)) { + return $source; + } + $dest =& File_Archive::_convertToWriter($destToConvert); + return $source->extract($dest, $autoClose, $bufferSize); + } + + /** + * Create a writer that can be used to append files to an archive inside a source + * If the archive can't be found in the source, it will be created + * If source is set to null, File_Archive::toFiles will be assumed + * If type is set to null, the type of the archive will be determined looking at + * the extension in the URL + * stat is the array of stat (returned by stat() PHP function of Reader getStat()) + * to use if the archive must be created + * + * This function allows to create or append data to nested archives. Only one + * archive will be created and if your creation requires creating several nested + * archives, a PEAR error will be returned + * + * After this call, $source will be closed and should not be used until the + * returned writer is closed. + * + * @param File_Archive_Reader $source A reader where some files will be appended + * @param string $URL URL to reach the archive in the source. + * if $URL is null, a writer to append files to the $source reader will + * be returned + * @param bool $unique If true, the duplicate files will be deleted on close + * Default is false (and setting it to true may have some performance + * consequences) + * @param string $type Extension of the archive (or null to use the one in the URL) + * @param array $stat Used only if archive is created, array of stat as returned + * by PHP stat function or Reader getStat function: stats of the archive) + * Time (index 9) will be overwritten to current time + * @return File_Archive_Writer a writer that you can use to append files to the reader + */ + function appenderFromSource(&$toConvert, $URL = null, $unique = null, + $type = null, $stat = array()) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + if ($unique == null) { + $unique = File_Archive::getOption("appendRemoveDuplicates"); + } + + //Do not report the fact that the archive does not exist as an error + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + + if ($URL === null) { + $result =& $source; + } else { + if ($type === null) { + $result = File_Archive::_readSource($source, $URL.'/', $reachable, $baseDir); + } else { + $result = File_Archive::readArchive( + $type, + File_Archive::_readSource($source, $URL, $reachable, $baseDir) + ); + } + } + + PEAR::popErrorHandling(); + + if (!PEAR::isError($result)) { + if ($unique) { + require_once "File/Archive/Writer/UniqueAppender.php"; + return new File_Archive_Writer_UniqueAppender($result); + } else { + return $result->makeAppendWriter(); + } + } + + //The source can't be found and has to be created + $stat[9] = $stat['mtime'] = time(); + + if (empty($baseDir)) { + if ($source !== null) { + $writer =& $source->makeWriter(); + } else { + $writer =& File_Archive::toFiles(); + } + if (PEAR::isError($writer)) { + return $writer; + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $result = File_Archive::toArchive($reachable, $writer, $type); + PEAR::popErrorHandling(); + + if (PEAR::isError($result)) { + $result = File_Archive::toFiles($reachable); + } + } else { + $reachedSource = File_Archive::readSource($source, $reachable); + if (PEAR::isError($reachedSource)) { + return $reachedSource; + } + $writer = $reachedSource->makeWriter(); + if (PEAR::isError($writer)) { + return $writer; + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $result = File_Archive::toArchive($baseDir, $writer, $type); + PEAR::popErrorHandling(); + + if (PEAR::isError($result)) { + require_once "File/Archive/Writer/AddBaseName.php"; + $result = new File_Archive_Writer_AddBaseName( + $baseDir, $writer); + if (PEAR::isError($result)) { + return $result; + } + } + } + return $result; + } + + /** + * Create a writer that allows appending new files to an existing archive + * This function actes as appendToSource with source being the system files + * $URL can't be null here + * + * @param File_Archive_Reader $source A reader where some files will be appended + * @return File_Archive_Writer a writer that you can use to append files to the reader + */ + function appender($URL, $unique = null, $type = null, $stat = array()) + { + $source = null; + return File_Archive::appenderFromSource($source, $URL, $unique, $type, $stat); + } + + /** + * Remove the files that follow a given predicate from the source + * If URL is null, the files will be removed from the source directly + * Else, URL must link to a source from which the files will be removed + * + * @param File_Archive_Predicate $pred The files that follow the predicate + * (for which $pred->isTrue($source) is true) will be erased + * @param File_Archive_Reader $source A reader that contains the files to remove + */ + function removeFromSource(&$pred, &$toConvert, $URL = null) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + if ($URL === null) { + $result = &$source; + } else { + if (substr($URL, -1) !== '/') { + $URL .= '/'; + } + $result = File_Archive::readSource($source, $URL); + } + + $writer = $result->makeWriterRemoveFiles($pred); + if (PEAR::isError($writer)) { + return $writer; + } + $writer->close(); + } + + /** + * Remove the files that follow a given predicate from the archive specified + * in $URL + * + * @param $URL URL of the archive where some files must be removed + */ + function remove($pred, $URL) + { + $source = null; + return File_Archive::removeFromSource($pred, $source, $URL); + } + + /** + * Remove duplicates from a source, keeping the most recent one (or the one that has highest pos in + * the archive if the files have same date or no date specified) + * + * @param File_Archive_Reader a reader that may contain duplicates + */ + function removeDuplicatesFromSource(&$toConvert, $URL = null) + { + $source =& File_Archive::_convertToReader($toConvert); + if (PEAR::isError($source)) { + return $source; + } + if ($URL !== null && substr($URL, -1) != '/') { + $URL .= '/'; + } + + if ($source === null) { + $source = File_Archive::read($URL); + } + + require_once "File/Archive/Predicate/Duplicate.php"; + $pred = new File_Archive_Predicate_Duplicate($source); + $source->close(); + return File_Archive::removeFromSource( + $pred, + $source, + null + ); + } + + /** + * Remove duplicates from the archive specified in the URL + */ + function removeDuplicates($URL) + { + $source = null; + return File_Archive::removeDuplicatesFromSource($source, $URL); + } +} + +?> \ No newline at end of file -- libgit2 0.21.4