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):
+ *
+ *
+ * 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