Compare commits

..

No commits in common. "master" and "4.0.0" have entirely different histories.

1742 changed files with 60458 additions and 257014 deletions

View File

@ -1,8 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
indent_style = tab
indent_size = 2

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
*.tar.gz
SeedDMS_*/*.tgz
ext/*
webapp/*

View File

@ -1,43 +0,0 @@
Options -Indexes
<IfModule mod_headers.c>
Header set Strict-Transport-Security: "max-age=15768000; includeSubDomains; preload"
Header set X-Content-Type-Options: "nosniff"
</IfModule>
RewriteEngine On
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#RewriteRule "^favicon\.ico$" "-" [L]
#RewriteRule "^(favicon\.ico)$" %{HTTP_HOST}/views/bootstrap/images/favicon.svg [L,NC]
RewriteRule "^(favicon\.ico)" /views/bootstrap/images/favicon.svg [L,NC]
# Store the current location in an environment variable CWD to use
# mod_rewrite in .htaccess files without knowing the RewriteBase
RewriteCond $0#%{REQUEST_URI} ([^#]*)#(.*)\1$
RewriteRule ^.*$ - [E=CWD:%2]
# Do not allow access on the other directories in www
RewriteRule "^utils/.*$" "" [F]
RewriteRule "^doc/.*$" "" [F]
# Anything below the following dirs will never be rewritten
RewriteRule "^pdfviewer/.*$" "-" [L]
RewriteRule "^views/.*/images.*$" "-" [L]
RewriteRule "^out/images.*$" "-" [L]
RewriteRule "^styles/.*$" "-" [L]
# Accessing a file in an extension is only possible in one
# of the directories op, out. res
# Added for old extensions which do not use routes
RewriteRule ^ext/[^/]+/icon.(?:png|svg)$ - [L]
RewriteCond %{REQUEST_URI} "ext/[^/]+/"
RewriteRule !^ext/[^/]+/.*(?:op|out|res|node_modules) - [F]
RewriteCond %{REQUEST_URI} "ext/[^/]+/res/.*$" [NC]
RewriteRule !^ext/[^/]+/res/.*\.(?:css|js|png|gif|svg|ico|html|woff|ttf) - [F]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ext/.*$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ %{ENV:CWD}index.php [QSA,L]

1826
CHANGELOG

File diff suppressed because it is too large Load Diff

View File

@ -1,388 +0,0 @@
module.exports = function (grunt) {
'use strict';
// if you set bootstrapDir to views/bootstrap/vendors then make sure
// bootbox is not installed, because version 5 of bootbox will not work
// with bootstrap 2
var bootstrapDir = 'views/bootstrap4/vendors',
tdkDir = 'views/tdk/vendors',
nodeDir = 'node_modules';
grunt.initConfig({
clean: {
vendors: [ bootstrapDir ]
},
copy: {
'bootstrap': {
files: [{
expand: true,
src: [
nodeDir + '/jquery/dist/*'
],
dest: bootstrapDir + '/jquery',
flatten: true
}, {
expand: true,
src: [
nodeDir + '/chartjs/chart.js',
nodeDir + '/chartjs/README.md',
nodeDir + '/chartjs/LICENSE'
],
dest: bootstrapDir + '/chartjs',
flatten: true
},{
expand: true,
src: [
nodeDir + '/cytoscape/dist/*',
nodeDir + '/cytoscape-grid-guide/cytoscape-grid-guide.js'
],
dest: bootstrapDir + '/cytoscape',
flatten: true
},{
expand: true,
src: [
nodeDir + '/jqtree/tree.jquery.js',
nodeDir + '/jqtree/jqtree.css'
],
dest: bootstrapDir + '/jqtree',
flatten: true
},{
expand: true,
src: [
nodeDir + '/noty/js/noty/jquery.noty.js'
],
dest: bootstrapDir + '/noty',
flatten: true
},{
expand: true,
src: [
nodeDir + '/noty/js/noty/themes/*'
],
dest: bootstrapDir + '/noty/themes',
flatten: true
},{
expand: true,
src: [
nodeDir + '/noty/js/noty/layouts/*'
],
dest: bootstrapDir + '/noty/layouts',
flatten: true
},{
expand: true,
src: [
nodeDir + '/select2/dist/js/*'
],
dest: bootstrapDir + '/select2/js',
flatten: true
},{
expand: true,
src: [
nodeDir + '/select2/dist/js/i18n/*'
],
dest: bootstrapDir + '/select2/js/i18n',
flatten: true
},{
expand: true,
src: [
nodeDir + '/select2/dist/css/*'
],
dest: bootstrapDir + '/select2/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/@ttskch/select2-bootstrap4-theme/dist/*'
],
dest: bootstrapDir + '/select2-bootstrap4-theme',
flatten: true
},{
expand: true,
src: [
nodeDir + '/vis-timeline/dist/*'
],
dest: bootstrapDir + '/vis-timeline',
flatten: true
},{
expand: true,
src: [
nodeDir + '/fine-uploader/jquery.fine-uploader/*'
],
dest: bootstrapDir + '/fine-uploader',
flatten: true
},{
expand: true,
src: [
nodeDir + '/jquery-validation/dist/*'
],
dest: bootstrapDir + '/jquery-validation',
flatten: true
},{
expand: true,
src: [
nodeDir + '/jquery-typeahead/dist/*'
],
dest: bootstrapDir + '/jquery-typeahead',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootbox/dist/*'
],
dest: bootstrapDir + '/bootbox',
flatten: true
},{
expand: true,
src: [
nodeDir + '/flot/source/jquery.canvaswrapper.js',
nodeDir + '/flot/source/jquery.colorhelpers.js',
nodeDir + '/flot/source/jquery.flot.*'
],
dest: bootstrapDir + '/flot',
flatten: true
},{
expand: true,
src: [
nodeDir + '/font-awesome/fonts/*'
],
dest: bootstrapDir + '/font-awesome/fonts',
flatten: true
},{
expand: true,
src: [
nodeDir + '/font-awesome/css/*'
],
dest: bootstrapDir + '/font-awesome/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/fullcalendar/LICENSE.txt',
nodeDir + '/fullcalendar/dist/*'
],
dest: bootstrapDir + '/fullcalendar',
flatten: true
},{
expand: true,
src: [
nodeDir + '/fullcalendar/dist/locale/*'
],
dest: bootstrapDir + '/fullcalendar/locale',
flatten: true
},{
expand: true,
src: [
nodeDir + '/moment/LICENSE.txt',
nodeDir + '/moment/min/*'
],
dest: bootstrapDir + '/moment',
flatten: true
},{
expand: true,
src: [
nodeDir + '/moment/dist/locale/*'
],
dest: bootstrapDir + '/moment/locale',
flatten: true
},{
expand: true,
src: [
nodeDir + '/popper.js/dist/umd/*'
],
dest: bootstrapDir + '/popper',
flatten: true
},{
expand: true,
src: [
nodeDir + '/perfect-scrollbar/dist/*'
],
dest: bootstrapDir + '/perfect-scrollbar',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap/dist/js/bootstrap.min.js',
nodeDir + '/bootstrap/dist/css/bootstrap.min.css'
],
dest: bootstrapDir + '/bootstrap',
flatten: true
},{
expand: true,
src: [
nodeDir + '/spectrum-colorpicker2/dist/spectrum.min.js',
nodeDir + '/spectrum-colorpicker2/dist/spectrum.min.css'
],
dest: bootstrapDir + '/spectrum-colorpicker2',
flatten: true
},{
expand: true,
src: [
nodeDir + '/jquery-lazy/jquery.lazy.min.js',
nodeDir + '/jquery-lazy/jquery.lazy.plugins.js'
],
dest: bootstrapDir + '/jquery-lazy',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap-datepicker/dist/js/*'
],
dest: bootstrapDir + '/bootstrap-datepicker/js',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap-datepicker/dist/css/*'
],
dest: bootstrapDir + '/bootstrap-datepicker/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap-datepicker/dist/locales/*'
],
dest: bootstrapDir + '/bootstrap-datepicker/locales',
flatten: true
}]
},
'tdk': {
files: [{
expand: true,
src: [
nodeDir + '/jquery/dist/*'
],
dest: tdkDir + '/jquery',
flatten: true
}, {
expand: true,
src: [
nodeDir + '/@coreui/coreui/dist/js/*'
],
dest: tdkDir + '/@coreui/coreui/js',
flatten: true
},{
expand: true,
src: [
nodeDir + '/@coreui/coreui/dist/css/*'
],
dest: tdkDir + '/@coreui/coreui/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/@coreui/icons/css/*'
],
dest: tdkDir + '/@coreui/icons/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/@coreui/icons/fonts/*'
],
dest: tdkDir + '/@coreui/icons/fonts',
flatten: true
},{
expand: true,
src: [
nodeDir + '/popper.js/dist/esm/*'
],
dest: tdkDir + '/popper.js',
flatten: true
},{
expand: true,
src: [
nodeDir + '/perfect-scrollbar/dist/*'
],
dest: tdkDir + '/perfect-scrollbar',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap/dist/js/*'
],
dest: tdkDir + '/bootstrap/js',
flatten: true
},{
expand: true,
src: [
nodeDir + '/bootstrap/dist/css/*'
],
dest: tdkDir + '/bootstrap/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/font-awesome/fonts/*'
],
dest: tdkDir + '/font-awesome/fonts',
flatten: true
},{
expand: true,
src: [
nodeDir + '/font-awesome/css/*'
],
dest: tdkDir + '/font-awesome/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/pace-progressbar/index.js'
],
dest: tdkDir + '/pace-progressbar',
flatten: true
},{
expand: true,
src: [
nodeDir + '/pace-progressbar/themes/*'
],
dest: tdkDir + '/pace-progressbar/themes',
flatten: true
},{
expand: true,
src: [
nodeDir + '/pace-progressbar/templates/*'
],
dest: tdkDir + '/pace-progressbar/templates',
flatten: true
},{
expand: true,
src: [
nodeDir + '/flag-icon-css/css/*'
],
dest: tdkDir + '/flag-icon-css/css',
flatten: true
},{
expand: true,
src: [
nodeDir + '/simple-line-icons/dist/fonts/*'
],
dest: tdkDir + '/simple-line-icons/fonts',
flatten: true
},{
expand: true,
src: [
nodeDir + '/simple-line-icons/dist/styles/*'
],
dest: tdkDir + '/simple-line-icons/css',
flatten: true
}]
},
}
});
grunt.registerTask('createVendorDir', 'Creates the necessary vendor directory', function() {
// Create the bootstrapDir when it doesn't exists.
if (!grunt.file.isDir(bootstrapDir)) {
grunt.file.mkdir(bootstrapDir);
// Output a success message
grunt.log.oklns(grunt.template.process(
'Directory "<%= directory %>" was created successfully.',
{ data: { directory: bootstrapDir } }
));
}
});
grunt.registerTask('default', [ 'clean', 'createVendorDir', 'copy' ]);
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
};

View File

@ -1,39 +1,17 @@
VERSION=$(shell php -r 'include("inc/inc.Version.php"); $$v=new SeedDMS_Version(); echo $$v->version();') VERSION=4.0.0
SRC=CHANGELOG inc conf utils index.php .htaccess languages op out controllers doc TODO LICENSE webdav install restapi pdfviewer SRC=CHANGELOG inc conf utils index.php languages views op out README.md README.Notification README.Ubuntu drop-tables-innodb.sql styles js TODO LICENSE Makefile webdav install
VIEWS ?= bootstrap bootstrap4 #restapi webapp
NODISTFILES=utils/importmail.php utils/seedddms-importmail utils/remote-email-upload utils/remote-upload utils/da-bv-reminder.php utils/seeddms-da-bv-reminder utils/relodge.php utils/seeddms-relodge .svn .gitignore
PHPDOC=~/Downloads/phpDocumentor.phar
dist: dist:
mkdir -p tmp/seeddms-$(VERSION) mkdir -p tmp/seeddms-$(VERSION)
cp -a $(SRC) tmp/seeddms-$(VERSION) cp -a $(SRC) tmp/seeddms-$(VERSION)
mkdir -p tmp/seeddms-$(VERSION)/views (cd tmp; tar --exclude=.svn -czvf ../seeddms-$(VERSION).tar.gz seeddms-$(VERSION))
mkdir -p tmp/seeddms-$(VERSION)/styles
for view in $(VIEWS) ; do \
if [ -d "views/$$view" ] ; then \
cp -a views/$$view tmp/seeddms-$(VERSION)/views ; \
fi ; \
if [ -d "styles/$$view" ] ; then \
cp -a styles/$$view tmp/seeddms-$(VERSION)/styles ; \
fi ; \
done
(cd tmp/seeddms-$(VERSION); rm -rf $(NODISTFILES); mv conf conf.template)
(cd tmp; tar --exclude=.svn --exclude=.gitignore -czvf ../seeddms-$(VERSION).tar.gz seeddms-$(VERSION))
rm -rf tmp rm -rf tmp
quickstart:
php7.4 vendor/bin/phing -Dversion=$(VERSION) package
unittest:
vendor/bin/phing -Dversion=$(VERSION) phpunitfast
pear: pear:
(cd SeedDMS_Core/; pear package) (cd SeedDMS_Core/; pear package)
(cd SeedDMS_Lucene/; pear package) (cd SeedDMS_Lucene/; pear package)
(cd SeedDMS_Preview/; pear package) (cd SeedDMS_Preview/; pear package)
(cd SeedDMS_SQLiteFTS/; pear package)
webdav: webdav:
mkdir -p tmp/seeddms-webdav-$(VERSION) mkdir -p tmp/seeddms-webdav-$(VERSION)
@ -41,58 +19,7 @@ webdav:
(cd tmp; tar --exclude=.svn -czvf ../seeddms-webdav-$(VERSION).tar.gz seeddms-webdav-$(VERSION)) (cd tmp; tar --exclude=.svn -czvf ../seeddms-webdav-$(VERSION).tar.gz seeddms-webdav-$(VERSION))
rm -rf tmp rm -rf tmp
webapp:
mkdir -p tmp/seeddms-webapp-$(VERSION)
cp -a restapi webapp tmp/seeddms-webapp-$(VERSION)
(cd tmp; tar --exclude=.svn -czvf ../seeddms-webapp-$(VERSION).tar.gz seeddms-webapp-$(VERSION))
rm -rf tmp
repository:
mkdir -p tmp/seeddms-repository-$(VERSION)
cp -a repository/www repository/utils repository/doc tmp/seeddms-repository-$(VERSION)
rm -f tmp/seeddms-repository/utils/update-repository.log
mkdir -p tmp/seeddms-repository-$(VERSION)/files
mkdir -p tmp/seeddms-repository-$(VERSION)/accounts
cp -a repository/files/.htaccess tmp/seeddms-repository-$(VERSION)/files
cp -a repository/accounts/.htaccess tmp/seeddms-repository-$(VERSION)/accounts
cp inc/inc.ClassExtensionMgr.php tmp/seeddms-repository-$(VERSION)/utils
(cd tmp; tar --exclude=.svn -czvf ../seeddms-repository-$(VERSION).tar.gz seeddms-repository-$(VERSION))
rm -rf tmp
doc: doc:
$(PHPDOC) -d SeedDMS_Core --ignore 'getusers.php,getfoldertree.php,config.php,reverselookup.php' --force -t html phpdoc -d SeedDMS_Core --ignore 'getusers.php,getfoldertree.php,config.php,reverselookup.php' -t html
# Download apigen with .PHONY: webdav
# composer create-project --no-dev apigen/apigen:^7.0@alpha tools/apigen
apidoc:
tools/apigen/bin/apigen SeedDMS_Core/Core --exclude "tests/*" --output html
# Turn the package.xml file into CHANGELOG.md
#
# The idea is to form blocks of lines separated by an empty line.
# Echo block consists of the version number, release date und notes.
# This blocks are turned into single lines which are than sorted.
# Afterwards the single lines are turned back into blocks.
#
# It first uses sgrep to extract the version, date und notes. This is
# feed to sed to isolated the date and version and put them on separate
# lines. Each version
# forms a block of n lines with the first two being the version and date.
# All remaining lines are notes. Blocks are separated by an empty line.
# It's important to form blocks without ane empty lines because the following
# awk will create a single line from each block which can then be sorted
# (or simply reversed in order).
# Because the blocks are listed in the wrong order (last version first and
# previous version last, e.g. 5.1.29, 3.3.0, 3.3.1, ...., 5.1.27, 5.1.28) they
# need to be reversed in order. This is done by turning each block into line
# with the former new lines replaced by a '|'. So it's basically a '|' separated
# csv file which is then reversed in order by 'sort -r'. In order to separate
# blocks by a newline, each line of that output is appended by another
# line break. Result is put back
# into the original format by replacing all '|' by newline.
#
PKGFILE=SeedDMS_Core/package.xml
changelog:
@sgrep 'stag("DATE") .. etag("DATE") or ((stag("RELEASE") .. etag("RELEASE")) in (stag("VERSION") .. etag("VERSION"))) or inner(stag("NOTES") __ etag("NOTES"))' ${PKGFILE} | sed -e 's#^ *<date>\([-0-9]*\)</date><release>\([0-9.preRC]*\)</release>#\n\n\2 (\1)\n---------------------#' | awk -F'\n' -vRS='' -vOFS='|' '{$$1=$$1}1' | sort -V -r | sed 's/$$/\n/' | tr '|' '\n'
.PHONY: doc webdav webapp repository changelog

View File

@ -3,17 +3,7 @@ Notifications
Most changes made to documents or folders in SeedDMS can be monitored Most changes made to documents or folders in SeedDMS can be monitored
by the users. Notifications are send by email if a user or group by the users. Notifications are send by email if a user or group
has subscribed to it. Setting up email is often troublesome, if you has subscribed it.
are not running SeedDMS on a Linux server with a running mail server.
In that case you do not have to fill out any of the email settings
except for the From address ('Send from' on the 'System' tab of the
configuration). Mail is send by PHP's mail() function. If the SMTP
host in the configuration is filled out, SeedDMS will use the PEAR
Mail package for delivering mail to the configured server. If you
also fill out the SMTP user, authentication with the SMTP server
will also be done. Some servers like smtp.gmail.com may still complain
about an invalid authentification. You should then check in your
google account if less secure apps are allowed.
The following notifications are send to all users and groups having The following notifications are send to all users and groups having
registered a notification for the event: registered a notification for the event:
@ -94,60 +84,11 @@ op/op.RemoveVersion.php
* version of document was removed * version of document was removed
subscribers of the document subscribers of the document
op/op.RemoveWorkflowFromDocument.php
* Workflow has been removed from document version
subscribers of the document
op/op.ReturnFromSubWorkflow.php
* Subworkflow has been ended and parent workflow will be continued
subscribers of the document
op/op.ReviewDocument.php op/op.ReviewDocument.php
* document was reviewed * document was reviewed
subscribers of the document subscribers of the document
op/op.SetReviewersApprovers.php op/op.UpdateDocument2.php
* Reviewers/approvers were added/deleted
subscribers of the document
uploader of version
op/op.RewindWorkflow.php
* Workflow was rewind to beginning
subscribers of the document
op/op.RunSubWorkflow.php
* Subworkflow was started
subscribers of the document
op/op.TriggerWorkflow.php
* Workflow transition was triggered
subscribers of the document
op/op.UpdateDocument.php op/op.UpdateDocument.php
* document was updated * document was updated
subscribers of the document subscribers of the document
op/op.ReceiptDocument.php
* document was received
subscribers of the document
op/op.ReviseDocument.php
* document was revised
subscribers of the document
op/op.SetRevisors.php
* Revisors were added/deleted
subscribers of the document
uploader of version
revisor
op/op.ReceiptDocument.php
* document was receipt
subscribers of the document
op/op.SetRecipients.php
* Recipients were added/deleted
subscribers of the document
uploader of version
recipient

View File

@ -27,7 +27,7 @@ transition: a transition is the change from one state to a new state
trigger a transition: a user runs an action on the document which possibly trigger a transition: a user runs an action on the document which possibly
changes the state. Internally this is identical to triggering a transition. changes the state. Internally this is identical to triggering a transition.
Such a trigger may or may not change the state of the document, Such a trigger may or may not change the statei of the document,
because there could because there could
be other users which also have to trigger the transition. be other users which also have to trigger the transition.
After each trigger of an transition it will After each trigger of an transition it will
@ -51,7 +51,7 @@ there are a number of possible transitions ending in a new state. Each
transition can only be triggered if the user has the right to do so. transition can only be triggered if the user has the right to do so.
A workflow can be assigned to a document just like any other attribute A workflow can be assigned to a document just like any other attribute
if the user has sufficient rights. Once a workflow is assigned, the document if the user has right access. Once a workflow is assigned the document
will be in the initial state of the workflow. As long as the workflow will be in the initial state of the workflow. As long as the workflow
has not left its initial state, it can be removed from the document by has not left its initial state, it can be removed from the document by
any users with write permission on the document. Once it has left the any users with write permission on the document. Once it has left the

368
README.md Normal file
View File

@ -0,0 +1,368 @@
SeedDMS Installation Instructions
==================================
NOTE FOR VERSION 4.0.0
======================
Since version 4.0.0 of SeedDMS installation has been simplified.
ADOdb is no longer needed because the database access is done by
PDO.
IMPORTANT NOTE ABOUT TRANSLATIONS
=================================
As you can see SeedDMS provides a lot of languages but we are not professional
translators and therefore rely on user contributions.
If your language is not present in the login panel:
- copy the language/English/ folder and rename it appropriately for your
language
- open the file `languages/your_lang/lang.inc` and translate it
- open the help file `languages/your_lang/help.htm` and translate it too
If you see some wrong or not translated messages:
- open the file `languages/your_lang/lang.inc`
- search the wrong messages and translate them
if you have some "error getting text":
- search the string in the english file `languages/english/lang.inc`
- copy to your language file `languages/your_lang/lang.inc`
- translate it
If there is no help in your language:
- Copy the English help `english/help.htm` file to your language folder
- translate it
If you apply any changes to the language files please send them to the
SeedDMS developers <info@seeddms.org>.
REQUIREMENTS
============
SeedDMS is a web-based application written in PHP. It uses the MySQL RDBMS
or sqlite3 to manage the documents that were uploaded into the application.
Make sure you have PHP 5.3 and MySQL 5 or higher installed. SeedDMS
will work with PHP running in CGI-mode as well as running as module under
apache. If you want to give your users the opportunity of uploading passport
photos you have to enable the gd-library (but the rest of SeedDMS will
work without gd, too).
Here is a detailed list of requirements:
1. A web server with at least php 5.3
2. A mysql database, unless you use sqlite
3. The php installation must have support for `pdo_mysql` or `pdo_sqlite`,
`php_gd2`, `php_mbstring`
4. Various command line programms to convert files into text for indexing
pdftotext, catdoc, xls2csv or scconvert, cat, id3 (optional, only needed
for fulltext search)
5. The Zend Framework (version 1) (optional, only needed for fulltext search)
6. The pear Log package
7. The pear HTTP_WebDAV_Server package (optional, only need for webdav)
BEFORE YOU START
================
SeedDMS has changed its installation process with version 3.0.0. This gives
you many more options in how to install SeedDMS. First of all, SeedDMS was
split into a core package (`SeedDMS_Core-<version>.tar.gz`) and the web
application itself (`seeddms-<version>.tar.gz`). The core is a pear package
which could be installed as one. It is responsible for all the database
operations. The web application contains the ui not knowing anything about
the database layout. Second, one SeedDMS installation can be used for
various customer instances by sharing a common source. Starting with
version 3.2.0 a full text search engine has been added. This requires
the zend framework and another pear package `SeedDMS_Lucene-<version>.tar.gz`
which can be downloaded from the SeedDMS web page. Version 4.0.0 show
preview images of documents which requires `SeedDMS_Preview-<version>.tar.gz`.
Finally, SeedDMS has
got a web based installation, which takes care of most of the installation
process.
Before you proceed you have to decide how to install SeedDMS:
1. with multiple instances
2. as a single instance
Both have its pros and cons, but
1. setting up a single instance is easier if you have no shell access to
the web server
2. the installation script is only tested for single instances
Installation for multiple instances shares the same source by many
instances but requires to create links which is not in any case possible
on your web server.
0. Some preparation
-------------------
A common source of problems in the past have been the additional software
packages needed by SeedDMS. Those are the PEAR packages `Log` and
`HTTP_WebDAV_Server` as well as the `Zend_Framework`.
If you have full access to the server running a Linux distribution it is
recommended to install those with your package manager if they are provided
by your Linux distribution. If you cannot install it this way then choose
a directory (preferable not below your web document root), unpack the
software into it and extend the php include path with your newly created
directory. Extending the php include can be either done by modifying
php.ini or adding a line like
> php_value include_path '/home/mypath:.:/usr/share/php'
to your apache configuration or setting the `extraPath` configuration
variable of SeedDMS.
For historical reasons the path to the SeedDMS_Core and SeedDMS_Lucene package
can still be set
in the configuration, which is not recommend anymore. Just leave those
parameters empty.
1. Using the installation tool
------------------------------
Unpack seeddms-<version>.tar.gz below the document root of
your web server.
Install `SeedDMS_Preview-<version>.tar.gz` and
`SeedDMS_Core-<version>.tar.gz` either as a regular pear package or
set up a file system structure like pear did somewhere on you server.
For the full text search engine support, you will also
need to install `SeedDMS_Lucene-<version>.tar.gz`.
For the following instructions we will assume a structure like above
and seeddms-<version> being accessible through
http://localhost/seeddms/
* Point you web browser towards http://hostname/seeddms/install/
* Follow the instructions on the page and create a file `ENABLE_INSTALL_TOOL`
in the conf directory.
* Create a data directory with the thre sub directories staging, cache
and lucene.
Make sure the data directory is either *not* below your document root
or is protected with a .htaccess file against web access. The data directory
needs to be writable by the web server.
* Clicking on 'Start installation' will show a form with all necessary
settings for a basic installation.
* After saving your settings succesfully you are ready to log in as admin and
continue customizing your installation with the 'Admin Tools'
2. Detailed installation instructions (single instance)
-------------------------------------------------------
You need a working web server with MySQL/PHP5 support and the files
`SeedDMS-<version>.tar.gz`, `SeedDMS_Preview-<version>.tar.gz` and
`SeedDMS_Core-<version>.tgz`. For the
full text search engine support, you will also need to unpack
`SeedDMS_Lucene-<version>.tgz`.
* Unpack all the files in a public web server folder. If you're working on
a host machine your provider will tell you where to upload the files.
If possible, do not unpack the pear packages `SeedDMS_Core-<version>.tgz`,
`SeedDMS_Preview-<version>.tgz` and
`SeedDMS_Lucene-<version>.tgz` below the document root of your web server.
Choose a temporary folder, as the files will be moved in a second.
Create a directory e.g. `pear` in the same directory where you unpacked
seeddms and create a sub directory SeedDMS. Move the content except for the
`tests` directory of all SeedDMS pear
packages into that directory. Please note that `pear/SeedDMS` may not
(and for security reasons should not) be below your document root.
You will end up with a directory structure like the following
> seeddms-<version>
> pear
> SeedDMS
> Core.php
> Core
> Lucene.php
> Lucene
> Preview
> Preview.php
Since they are pear packages they can also be installed with
> pear install SeedDMS_Core-<version>.tgz
> pear install SeedDMS_Lucene-<version>.tgz
> pear install SeedDMS_Preview-<version>.tgz
* The PEAR package Log is also needed. It can be downloaded from
http://pear.php.net/package/Log. Either install it as a pear package
or place it under your new directory 'pear'
> pear
> Log
> Log.php
* The package HTTP_WebDAV_Server is also needed. It can be downloaded from
http://pear.php.net/package/HTTP_WebDAV_Server. Either install it as a
pear package or place it under your new directory 'pear'
> pear
> HTTP
> WebDAV
> Server
> Server.php
* Create a data folder somewhere on your web server including the subdirectories
staging, cache and lucene and make sure they are writable by your web server,
but not accessible through the web.
For security reason the data folder should not be inside the public folders
or should be protected by a .htaccess file.
If you install SeedDMS for the first time continue with the database setup.
* Create a new database on your web server
e.g. for mysql:
create database seeddms;
* Create a new user for the database with all permissions on the new database
e.g. for mysql:
grant all privileges on seeddms.* to seeddms@localhost identified by 'secret';
(replace 'secret' with you own password)
* Optionally import `create_tables-innodb.sql` in the new database
e.g. for mysql:
> cat create_tables-innodb.sql | mysql -useeddms -p seeddms
This step can also be done by the install tool.
* create a file `ENABLE_INSTALL_TOOL` in the conf directory and point
your browser at http://hostname/seeddms/install
NOTE: UPDATING FROM A PREVIOUS VERSION OR SEEDDMS
As SeedDMS is a smooth continuation of SeedDMS there is no difference
in updating from SeedDMS or SeedDMS
- make a backup archive of your installation folder
- make a backup archive of your data folder
- dump your current database
- extract the SeedDMS archive to your web server
- edit the conf/settings.xml file to match your previuos settings
(you can even replace the file with your own one eventualy adding by hand
the missing new parameters)
- create a file `ENABLE_INSTALL_TOOL` in the conf directory and point
your browser at http://hostname/seeddms/install
The install tool will detect the version of your current SeedDMS installation
and run the required database updates.
3. Email Notification
---------------------
A notification system allows users to receive an email when a
document or folder is changed. This is an event-based mechanism that
notifies the user as soon as the change has been made and replaces the
cron mechanism originally developed. Any user that has read access to a
document or folder can subscribe to be notified of changes. Users that
have been assigned as reviewers or approvers for a document are
automatically added to the notification system for that document.
A new page has been created for users to assist with the management of
their notification subscriptions. This can be found in the "My Account"
section under "Notification List".
4. Nearly finished
------------------
Now point your browser to http://hostname/seeddms/index.php
and login with "admin" both as username and password.
After having logged in you should first choose "My Account" and
change the Administrator's password and email-address.
CONFIGURING MULTIPLE INSTANCES
==============================
Since version 3.0.0, SeedDMS can be set up to run several parallel instances
sharing the same source but each instance has its own configuration. This is
quite useful if you intend to host SeedDMS for several customers. This
approach still allows to have diffenrent version of SeedDMS installed
and will not force you to upgrade a customer instance, because other
instances are upgraded. A customer instance consists of
1. a directory containing mostly links to the SeedDMS source and a
configuration file
2. a directory containing the document content files
3. a database
1. Unpack the SeedDMS distribution
----------------------------------
Actually there is no need to set up the database at this point but it won't
hurt since you'll need one in the next step anyway. The sources of SeedDMS
can be anywhere you like. The do not have to be in you www-root. If you just
have access to your www-root directory, then put them there.
2. Setup the instance
---------------------
Unpack the files as described in the quick installation.
Create a directory in your www-root or use www-root for your instance. In the
second case, you will not be able to create a second instance, because each
instance needs its own directory.
Go into that directory create the following links (<seeddms-source> is the
directory of your initial SeedDMS intallation).
> src -> <seeddms-source>
> inc -> src/inc
> op -> src/op
> out -> src/out
> js -> src/js
> views -> src/views
> languages -> src/languages
> styles -> src/styles
> themes -> src/themes
> install -> src/install
> index.php -> src/index.php
> ln -s ../seeddms-<version> src
> ln -s src/inc inc
> ln -s src/op op
> ln -s src/out out
> ln -s src/js js
> ln -s src/views views
> ln -s src/languages languages
> ln -s src/styles styles
> ln -s src/themes themes
> ln -s src/install install
> ln -s src/index.php index.php
Create a new directory named conf and run the installation tool.
Creating the links as above has the advantage that you can easily switch
to a new version and go back if it is necessary. You could even run various
instances of SeedDMS using different versions.
3. Create a database and data store for each instance
-----------------------------------------------------
Create a database and data store for each instance and adjust the database
settings in conf/settings.xml or run the installation tool.
Point your web browser towards the index.php file in your new instance.
LICENSING
=========
SeedDMS is licensed unter GPLv2
Jumploader is licensed as stated by the author on th web site
<http://jumploader.com/>
-- Taken from web site of jumploader ---
You may use this software for free, however, you should not:
- Decompile binaries.
- Alter or replace class and/or resource files.
- Redistribute this software under different name or authority.
If you would like a customized version, I can do this for a fee. Don't hesitate to contact me with questions or comments.
Uwe Steinmann <info@seeddms.org>

94
SeedDMS_Core/Core.php Normal file
View File

@ -0,0 +1,94 @@
<?php
/**
* Implementation of a document in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL2
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli,
* Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Matteo Lucarelli, 2010-2012 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* @uses SeedDMS_DatabaseAccess
*/
define('USE_PDO', 1);
if(defined('USE_PDO'))
require_once('Core/inc.DBAccessPDO.php');
else
require_once('Core/inc.DBAccess.php');
/**
* @uses SeedDMS_DMS
*/
require_once('Core/inc.ClassDMS.php');
/**
* @uses SeedDMS_Object
*/
require_once('Core/inc.ClassObject.php');
/**
* @uses SeedDMS_Folder
*/
require_once('Core/inc.ClassFolder.php');
/**
* @uses SeedDMS_Document
*/
require_once('Core/inc.ClassDocument.php');
/**
* @uses SeedDMS_Attribute
*/
require_once('Core/inc.ClassAttribute.php');
/**
* @uses SeedDMS_Group
*/
require_once('Core/inc.ClassGroup.php');
/**
* @uses SeedDMS_User
*/
require_once('Core/inc.ClassUser.php');
/**
* @uses SeedDMS_KeywordCategory
*/
require_once('Core/inc.ClassKeywords.php');
/**
* @uses SeedDMS_DocumentCategory
*/
require_once('Core/inc.ClassDocumentCategory.php');
/**
* @uses SeedDMS_Notification
*/
require_once('Core/inc.ClassNotification.php');
/**
* @uses SeedDMS_UserAccess
* @uses SeedDMS_GroupAccess
*/
require_once('Core/inc.ClassAccess.php');
/**
* @uses SeedDMS_Workflow
*/
require_once('Core/inc.ClassWorkflow.php');
/**
*/
require_once('Core/inc.AccessUtils.php');
/**
* @uses SeedDMS_File
*/
require_once('Core/inc.FileUtils.php');
?>

View File

@ -0,0 +1,90 @@
<?php
/**
* Some definitions for access control
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal,
* 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Used to indicate that a search should return all
* results in the ACL table. See {@link SeedDMS_Core_Folder::getAccessList()}
*/
define("M_ANY", -1);
/**
* No rights at all
*/
define("M_NONE", 1);
/**
* Read access only
*/
define("M_READ", 2);
/**
* Read and write access only
*/
define("M_READWRITE", 3);
/**
* Unrestricted access
*/
define("M_ALL", 4);
define ("O_GTEQ", ">=");
define ("O_LTEQ", "<=");
define ("O_EQ", "=");
/**
* Folder notification
*/
define("T_FOLDER", 1); //TargetType = Folder
/**
* Document notification
*/
define("T_DOCUMENT", 2); // " = Document
/**
* Notify on all actions on the folder/document
*/
define("N_ALL", 0);
/**
* Notify when object has been deleted
*/
define("N_DELETE", 1);
/**
* Notify when object has been moved
*/
define("N_MOVE", 2);
/**
* Notify when object has been updated (no new version)
*/
define("N_UPDATE", 3);
/**
* Notify when document has new version
*/
define("N_NEW_VERSION", 4);
/**
* Notify when version of document was deleted
*/
define("N_DELETE_VERSION", 5);
/**
* Notify when version of document was deleted
*/
define("N_ADD_DOCUMENT", 6);
?>

View File

@ -0,0 +1,76 @@
<?php
/**
* Implementation of user and group access object
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a user access right.
* This class cannot be used to modify access rights.
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_UserAccess { /* {{{ */
var $_user;
var $_mode;
function SeedDMS_Core_UserAccess($user, $mode) {
$this->_user = $user;
$this->_mode = $mode;
}
function getUserID() { return $this->_user->getID(); }
function getMode() { return $this->_mode; }
function isAdmin() {
return ($this->_mode == SeedDMS_Core_User::role_admin);
}
function getUser() {
return $this->_user;
}
} /* }}} */
/**
* Class to represent a group access right.
* This class cannot be used to modify access rights.
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_GroupAccess { /* {{{ */
var $_group;
var $_mode;
function SeedDMS_Core_GroupAccess($group, $mode) {
$this->_group = $group;
$this->_mode = $mode;
}
function getGroupID() { return $this->_group->getID(); }
function getMode() { return $this->_mode; }
function getGroup() {
return $this->_group;
}
} /* }}} */
?>

View File

@ -0,0 +1,488 @@
<?php
/**
* Implementation of the attribute object in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2012 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent an attribute in the document management system
*
* Attributes are key/value pairs which can be attachted to documents,
* folders and document content. The number of attributes is unlimited.
* Each attribute has a value and is related to an attribute definition,
* which holds the name and other information about the attribute.
*
* @see SeedDMS_Core_AttributeDefinition
*
* @category DMS
* @package SeedDMS_Core
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2012-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_Attribute { /* {{{ */
/**
* @var integer id of attribute
*
* @access protected
*/
protected $_id;
/**
* @var object SeedDMS_Core_Object folder, document or document content
* this attribute belongs to
*
* @access protected
*/
protected $_obj;
/**
* @var object SeedDMS_Core_AttributeDefinition definition of this attribute
*
* @access protected
*/
protected $_attrdef;
/**
* @var mixed value of this attribute
*
* @access protected
*/
protected $_value;
/**
* @var object SeedDMS_Core_DMS reference to the dms instance this attribute belongs to
*
* @access protected
*/
protected $_dms;
/**
* Constructor
*
* @param integer $id internal id of attribute
* @param SeedDMS_Core_Object $obj object this attribute is attached to
* @param SeedDMS_Core_AttributeDefinition $attrdef reference to the attribute definition
* @param string $value value of the attribute
*/
function SeedDMS_Core_Attribute($id, $obj, $attrdef, $value) { /* {{{ */
$this->_id = $id;
$this->_obj = $obj;
$this->_attrdef = $attrdef;
$this->_value = $value;
$this->_dms = null;
} /* }}} */
/**
* Set reference to dms
*
* @param SeedDMS_Core_DMS $dms
*/
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
function getID() { return $this->_id; }
function getValue() { return $this->_value; }
/**
* Set a value of an attribute
* The attribute is deleted completely if the value is the empty string
*
* @param string $value value to be set
* @return boolean true if operation was successfull, otherwise false
*/
function setValue($value) { /* {{{*/
$db = $this->_dms->getDB();
switch(get_class($this->_obj)) {
case "SeedDMS_Core_Document":
if(trim($value) === '')
$queryStr = "DELETE FROM tblDocumentAttributes WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
else
$queryStr = "UPDATE tblDocumentAttributes SET value = ".$db->qstr($value)." WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
break;
case "SeedDMS_Core_DocumentContent":
if(trim($value) === '')
$queryStr = "DELETE FROM tblDocumentContentAttributes WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
else
$queryStr = "UPDATE tblDocumentContentAttributes SET value = ".$db->qstr($value)." WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
break;
case "SeedDMS_Core_Folder":
if(trim($value) === '')
$queryStr = "DELETE FROM tblFolderAttributes WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
else
$queryStr = "UPDATE tblFolderAttributes SET value = ".$db->qstr($value)." WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
break;
default:
return false;
}
if (!$db->getResult($queryStr))
return false;
$this->_value = $value;
return true;
} /* }}} */
function getAttributeDefinition() { return $this->_attrdef; }
} /* }}} */
/**
* Class to represent an attribute definition in the document management system
*
* Attribute definitions specify the name, type, object type, minimum and
* maximum values and a value set. The object type determines the object
* an attribute may be attached to. If the object type is set to object_all
* the attribute can be used for documents, document content and folders.
*
* The type of an attribute specifies the skalar data type.
*
* Attributes for which multiple values are allowed must have the
* multiple flag set to true and specify a value set. A value set
* is a string consisting of n separated values. The separator is the
* first char of the value set. A possible value could be '|REV-A|REV-B'
* If multiple values are allowed, then minvalues and maxvalues may
* restrict the allowed number of values.
*
* @see SeedDMS_Core_Attribute
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2012 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_AttributeDefinition { /* {{{ */
/**
* @var integer id of attribute definition
*
* @access protected
*/
protected $_id;
/**
* @var string name of attribute definition
*
* @access protected
*/
protected $_name;
/**
* @var string object type of attribute definition. This can be one of
* type_int, type_float, type_string, or type_boolean.
*
* @access protected
*/
protected $_type;
/**
* @var string type of attribute definition. This can be one of objtype_all,
* objtype_folder, objtype_document, or objtype_documentcontent.
*
* @access protected
*/
protected $_objtype;
/**
* @var boolean whether an attribute can have multiple values
*
* @access protected
*/
protected $_multiple;
/**
* @var integer minimum values of an attribute
*
* @access protected
*/
protected $_minvalues;
/**
* @var integer maximum values of an attribute
*
* @access protected
*/
protected $_maxvalues;
/**
* @var string list of possible values of an attribute
*
* @access protected
*/
protected $_valueset;
/**
* @var object SeedDMS_Core_DMS reference to the dms instance this attribute definition belongs to
*
* @access protected
*/
protected $_dms;
/*
* Possible skalar data types of an attribute
*/
const type_int = '1';
const type_float = '2';
const type_string = '3';
const type_boolean = '4';
/*
* The object type for which a attribute may be used
*/
const objtype_all = '0';
const objtype_folder = '1';
const objtype_document = '2';
const objtype_documentcontent = '3';
/**
* Constructor
*
* @param integer $id internal id of attribute definition
* @param string $name name of attribute
* @param integer $objtype type of object for which this attribute definition
* may be used.
* @param integer $type skalar type of attribute
* @param boolean $multiple set to true if multiple values are allowed
* @param integer $minvalues minimum number of values
* @param integer $maxvalues maximum number of values
* @param string $valueset separated list of allowed values, the first char
* is taken as the separator
*/
function SeedDMS_Core_AttributeDefinition($id, $name, $objtype, $type, $multiple, $minvalues, $maxvalues, $valueset) { /* {{{ */
$this->_id = $id;
$this->_name = $name;
$this->_type = $type;
$this->_objtype = $objtype;
$this->_multiple = $multiple;
$this->_minvalues = $minvalues;
$this->_maxvalues = $maxvalues;
$this->_valueset = $valueset;
$this->_separator = '';
$this->_dms = null;
} /* }}} */
/**
* Set reference to dms
*
* @param SeedDMS_Core_DMS $dms
*/
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
function getID() { return $this->_id; }
function getName() { return $this->_name; }
function setName($name) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET name =".$db->qstr($name)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_name = $name;
return true;
} /* }}} */
function getObjType() { return $this->_objtype; }
function setObjType($objtype) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET objtype =".intval($objtype)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_objtype = $objtype;
return true;
} /* }}} */
function getType() { return $this->_type; }
function setType($type) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET type =".intval($type)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_type = $type;
return true;
} /* }}} */
function getMultipleValues() { return $this->_multiple; }
function setMultipleValues($mv) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET multiple =".intval($mv)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_multiple = $mv;
return true;
} /* }}} */
function getMinValues() { return $this->_minvalues; }
function setMinValues($minvalues) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET minvalues =".intval($minvalues)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_minvalues = $minvalues;
return true;
} /* }}} */
function getMaxValues() { return $this->_maxvalues; }
function setMaxValues($maxvalues) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET maxvalues =".intval($maxvalues)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_maxvalues = $maxvalues;
return true;
} /* }}} */
/**
* Get the value set as saved in the database
*
* @return string value set
*/
function getValueSet() { /* {{{ */
return $this->_valueset;
} /* }}} */
/**
* Get the whole value set as an array
*
* @return array values of value set or false if the value set has
* less than 2 chars
*/
function getValueSetAsArray() { /* {{{ */
if(strlen($this->_valueset) > 1)
return explode($this->_valueset[0], substr($this->_valueset, 1));
else
return false;
} /* }}} */
/**
* Get the n'th value of a value set
*
* @param interger $index
* @return string n'th value of value set or false if the index is
* out of range or the value set has less than 2 chars
*/
function getValueSetValue($ind) { /* {{{ */
if(strlen($this->_valueset) > 1) {
$tmp = explode($this->_valueset[0], substr($this->_valueset, 1));
if(isset($tmp[$ind]))
return $tmp[$ind];
else
return false;
} else
return false;
} /* }}} */
/**
* Set the value set
*
* A value set is a list of values allowed for an attribute. The values
* are separated by a char which must also be the first char of the
* value set string.
*
* @param string $valueset
* @return boolean true if value set could be set, otherwise false
*/
function setValueSet($valueset) { /* {{{ */
/*
$tmp = array();
foreach($valueset as $value) {
$tmp[] = str_replace('"', '""', $value);
}
$valuesetstr = implode(",", $tmp);
*/
$valuesetstr = $valueset;
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblAttributeDefinitions SET valueset =".$db->qstr($valuesetstr)." WHERE id = " . $this->_id;
$res = $db->getResult($queryStr);
if (!$res)
return false;
$this->_valueset = $valueset;
$this->_separator = substr($valueset, 0, 1);
return true;
} /* }}} */
/**
* Check if the attribute definition is used
*
* Checks all attributes whether at least one of them referenceѕ
* this attribute definition
*
* @return boolean true if attribute definition is used, otherwise false
*/
function isUsed() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE attrdef=".$this->_id;
$resArr = $db->getResultArray($queryStr);
if (is_array($resArr) && count($resArr) == 0) {
$queryStr = "SELECT * FROM tblFolderAttributes WHERE attrdef=".$this->_id;
$resArr = $db->getResultArray($queryStr);
if (is_array($resArr) && count($resArr) == 0) {
$queryStr = "SELECT * FROM tblDocumentContentAttributes WHERE attrdef=".$this->_id;
$resArr = $db->getResultArray($queryStr);
if (is_array($resArr) && count($resArr) == 0) {
return false;
}
}
}
return true;
} /* }}} */
/**
* Remove the attribute definition
* Removal is only executed when the definition is not used anymore.
*
* @return boolean true on success or false in case of an error
*/
function remove() { /* {{{ */
$db = $this->_dms->getDB();
if($this->isUsed())
return false;
// Delete user itself
$queryStr = "DELETE FROM tblAttributeDefinitions WHERE id = " . $this->_id;
if (!$db->getResult($queryStr)) return false;
return true;
} /* }}} */
} /* }}} */
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
<?php
/**
* Implementation of document categories in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a document category in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C)2011 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_DocumentCategory {
/**
* @var integer $_id id of document category
* @access protected
*/
protected $_id;
/**
* @var string $_name name of category
* @access protected
*/
protected $_name;
/**
* @var object $_dms reference to dms this category belongs to
* @access protected
*/
protected $_dms;
function SeedDMS_Core_DocumentCategory($id, $name) { /* {{{ */
$this->_id = $id;
$this->_name = $name;
$this->_dms = null;
} /* }}} */
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
function getID() { return $this->_id; }
function getName() { return $this->_name; }
function setName($newName) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblCategory SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id;
if (!$db->getResult($queryStr))
return false;
$this->_name = $newName;
return true;
} /* }}} */
function isUsed() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "SELECT * FROM tblDocumentCategory WHERE categoryID=".$this->_id;
$resArr = $db->getResultArray($queryStr);
if (is_array($resArr) && count($resArr) == 0)
return false;
return true;
} /* }}} */
function getCategories() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "SELECT * FROM tblCategory";
return $db->getResultArray($queryStr);
} /* }}} */
function addCategory($keywords) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "INSERT INTO tblCategory (category) VALUES (".$db->qstr($keywords).")";
return $db->getResult($queryStr);
} /* }}} */
function remove() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "DELETE FROM tblCategory WHERE id = " . $this->_id;
if (!$db->getResult($queryStr))
return false;
return true;
} /* }}} */
function getDocumentsByCategory() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "SELECT * FROM tblDocumentCategory where categoryID=".$this->_id;
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && !$resArr)
return false;
$documents = array();
foreach ($resArr as $row) {
array_push($documents, $this->_dms->getDocument($row["id"]));
}
return $documents;
} /* }}} */
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
<?php
/**
* Implementation of the group object in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a user group in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_Group {
/**
* The id of the user group
*
* @var integer
*/
protected $_id;
/**
* The name of the user group
*
* @var string
*/
protected $_name;
/**
* Back reference to DMS this user group belongs to
*
* @var object
*/
protected $_dms;
function SeedDMS_Core_Group($id, $name, $comment) { /* {{{ */
$this->_id = $id;
$this->_name = $name;
$this->_comment = $comment;
$this->_dms = null;
} /* }}} */
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
function getID() { return $this->_id; }
function getName() { return $this->_name; }
function setName($newName) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblGroups SET name = ".$db->qstr($newName)." WHERE id = " . $this->_id;
if (!$db->getResult($queryStr))
return false;
$this->_name = $newName;
return true;
} /* }}} */
function getComment() { return $this->_comment; }
function setComment($newComment) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblGroups SET comment = ".$db->qstr($newComment)." WHERE id = " . $this->_id;
if (!$db->getResult($queryStr))
return false;
$this->_comment = $newComment;
return true;
} /* }}} */
function getUsers() { /* {{{ */
$db = $this->_dms->getDB();
if (!isset($this->_users)) {
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
"WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."'";
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && $resArr == false)
return false;
$this->_users = array();
foreach ($resArr as $row) {
$user = new SeedDMS_Core_User($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']);
array_push($this->_users, $user);
}
}
return $this->_users;
} /* }}} */
function getManagers() { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "SELECT `tblUsers`.* FROM `tblUsers` ".
"LEFT JOIN `tblGroupMembers` ON `tblGroupMembers`.`userID`=`tblUsers`.`id` ".
"WHERE `tblGroupMembers`.`groupID` = '". $this->_id ."' AND tblGroupMembers.manager = 1";
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && $resArr == false)
return false;
$managers = array();
foreach ($resArr as $row) {
$user = new SeedDMS_Core_User($row["id"], $row["login"], $row["pwd"], $row["fullName"], $row["email"], $row["language"], $row["theme"], $row["comment"], $row["role"], $row['hidden']);
array_push($managers, $user);
}
return $managers;
} /* }}} */
function addUser($user,$asManager=false) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "INSERT INTO tblGroupMembers (groupID, userID, manager) VALUES (".$this->_id.", ".$user->getID(). ", " . ($asManager?"1":"0") ." )";
$res = $db->getResult($queryStr);
if ($res) return false;
unset($this->_users);
return true;
} /* }}} */
function removeUser($user) { /* {{{ */
$db = $this->_dms->getDB();
$queryStr = "DELETE FROM tblGroupMembers WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
$res = $db->getResult($queryStr);
if ($res) return false;
unset($this->_users);
return true;
} /* }}} */
// $asManager=false: verify if user is in group
// $asManager=true : verify if user is in group as manager
function isMember($user,$asManager=false) { /* {{{ */
if (isset($this->_users)&&!$asManager) {
foreach ($this->_users as $usr)
if ($usr->getID() == $user->getID())
return true;
return false;
}
$db = $this->_dms->getDB();
if ($asManager) $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID() . " AND manager = 1";
else $queryStr = "SELECT * FROM tblGroupMembers WHERE groupID = " . $this->_id . " AND userID = " . $user->getID();
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && $resArr == false) return false;
if (count($resArr) != 1) return false;
return true;
} /* }}} */
function toggleManager($user) { /* {{{ */
$db = $this->_dms->getDB();
if (!$this->isMember($user)) return false;
if ($this->isMember($user,true)) $queryStr = "UPDATE tblGroupMembers SET manager = 0 WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
else $queryStr = "UPDATE tblGroupMembers SET manager = 1 WHERE groupID = ".$this->_id." AND userID = ".$user->getID();
if (!$db->getResult($queryStr)) return false;
return true;
} /* }}} */
/**
* Delete user group
* This function deletes the user group and all it references, like access
* control lists, notifications, as a child of other groups, etc.
*
* @param object $user the user doing the removal (needed for entry in
* review log.
* @return boolean true on success or false in case of an error
*/
function remove($user) { /* {{{ */
$db = $this->_dms->getDB();
$db->startTransaction();
$queryStr = "DELETE FROM tblGroupMembers WHERE groupID = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblACLs WHERE groupID = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblNotify WHERE groupID = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblMandatoryReviewers WHERE reviewerGroupID = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblMandatoryApprovers WHERE approverGroupID = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblWorkflowTransitionGroups WHERE groupid = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblGroups WHERE id = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
// TODO : update document status if reviewer/approver has been deleted
$reviewStatus = $this->getReviewStatus();
foreach ($reviewStatus as $r) {
$queryStr = "INSERT INTO `tblDocumentReviewLog` (`reviewID`, `status`, `comment`, `date`, `userID`) ".
"VALUES ('". $r["reviewID"] ."', '-2', 'Review group removed from process', NOW(), '". $user->getID() ."')";
$res=$db->getResult($queryStr);
if(!$res) {
$db->rollbackTransaction();
return false;
}
}
$approvalStatus = $this->getApprovalStatus();
foreach ($approvalStatus as $a) {
$queryStr = "INSERT INTO `tblDocumentApproveLog` (`approveID`, `status`, `comment`, `date`, `userID`) ".
"VALUES ('". $a["approveID"] ."', '-2', 'Approval group removed from process', NOW(), '". $user->getID() ."')";
$res=$db->getResult($queryStr);
if(!$res) {
$db->rollbackTransaction();
return false;
}
}
$db->commitTransaction();
return true;
} /* }}} */
function getReviewStatus($documentID=null, $version=null) { /* {{{ */
$db = $this->_dms->getDB();
if (!$db->createTemporaryTable("ttreviewid")) {
return false;
}
$status = array();
// See if the group is assigned as a reviewer.
$queryStr = "SELECT `tblDocumentReviewers`.*, `tblDocumentReviewLog`.`status`, ".
"`tblDocumentReviewLog`.`comment`, `tblDocumentReviewLog`.`date`, ".
"`tblDocumentReviewLog`.`userID` ".
"FROM `tblDocumentReviewers` ".
"LEFT JOIN `tblDocumentReviewLog` USING (`reviewID`) ".
"LEFT JOIN `ttreviewid` on `ttreviewid`.`maxLogID` = `tblDocumentReviewLog`.`reviewLogID` ".
"WHERE `ttreviewid`.`maxLogID`=`tblDocumentReviewLog`.`reviewLogID` ".
($documentID==null ? "" : "AND `tblDocumentReviewers`.`documentID` = '". (int) $documentID ."' ").
($version==null ? "" : "AND `tblDocumentReviewers`.`version` = '". (int) $version ."' ").
"AND `tblDocumentReviewers`.`type`='1' ".
"AND `tblDocumentReviewers`.`required`='". $this->_id ."' ";
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && $resArr == false)
return false;
if (count($resArr)>0) {
foreach ($resArr as $res)
$status[] = $res;
}
return $status;
} /* }}} */
function getApprovalStatus($documentID=null, $version=null) { /* {{{ */
$db = $this->_dms->getDB();
if (!$db->createTemporaryTable("ttapproveid")) {
return false;
}
$status = array();
// See if the group is assigned as an approver.
$queryStr = "SELECT `tblDocumentApprovers`.*, `tblDocumentApproveLog`.`status`, ".
"`tblDocumentApproveLog`.`comment`, `tblDocumentApproveLog`.`date`, ".
"`tblDocumentApproveLog`.`userID` ".
"FROM `tblDocumentApprovers` ".
"LEFT JOIN `tblDocumentApproveLog` USING (`approveID`) ".
"LEFT JOIN `ttapproveid` on `ttapproveid`.`maxLogID` = `tblDocumentApproveLog`.`approveLogID` ".
"WHERE `ttapproveid`.`maxLogID`=`tblDocumentApproveLog`.`approveLogID` ".
($documentID==null ? "" : "AND `tblDocumentApprovers`.`documentID` = '". (int) $documentID ."' ").
($version==null ? "" : "AND `tblDocumentApprovers`.`version` = '". (int) $version ."' ").
"AND `tblDocumentApprovers`.`type`='1' ".
"AND `tblDocumentApprovers`.`required`='". $this->_id ."' ";
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && $resArr == false)
return false;
if (count($resArr)>0) {
foreach ($resArr as $res)
$status[] = $res;
}
return $status;
} /* }}} */
}
?>

View File

@ -0,0 +1,143 @@
<?php
/**
* Implementation of keyword categories in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a keyword category in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_KeywordCategory {
/**
* @var integer $_id id of keyword category
* @access protected
*/
protected $_id;
/**
* @var integer $_ownerID id of user who is the owner
* @access protected
*/
protected $_ownerID;
/**
* @var string $_name name of category
* @access protected
*/
protected $_name;
/**
* @var object $_dms reference to dms this category belongs to
* @access protected
*/
protected $_dms;
function SeedDMS_Core_KeywordCategory($id, $ownerID, $name) {
$this->_id = $id;
$this->_name = $name;
$this->_ownerID = $ownerID;
$this->_dms = null;
}
function setDMS($dms) {
$this->_dms = $dms;
}
function getID() { return $this->_id; }
function getName() { return $this->_name; }
function getOwner() {
if (!isset($this->_owner))
$this->_owner = $this->_dms->getUser($this->_ownerID);
return $this->_owner;
}
function setName($newName) {
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblKeywordCategories SET name = ".$db->qstr($newName)." WHERE id = ". $this->_id;
if (!$db->getResult($queryStr))
return false;
$this->_name = $newName;
return true;
}
function setOwner($user) {
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblKeywordCategories SET owner = " . $user->getID() . " WHERE id " . $this->_id;
if (!$db->getResult($queryStr))
return false;
$this->_ownerID = $user->getID();
$this->_owner = $user;
return true;
}
function getKeywordLists() {
$db = $this->_dms->getDB();
$queryStr = "SELECT * FROM tblKeywords WHERE category = " . $this->_id;
return $db->getResultArray($queryStr);
}
function editKeywordList($listID, $keywords) {
$db = $this->_dms->getDB();
$queryStr = "UPDATE tblKeywords SET keywords = ".$db->qstr($keywords)." WHERE id = $listID";
return $db->getResult($queryStr);
}
function addKeywordList($keywords) {
$db = $this->_dms->getDB();
$queryStr = "INSERT INTO tblKeywords (category, keywords) VALUES (" . $this->_id . ", ".$db->qstr($keywords).")";
return $db->getResult($queryStr);
}
function removeKeywordList($listID) {
$db = $this->_dms->getDB();
$queryStr = "DELETE FROM tblKeywords WHERE id = $listID";
return $db->getResult($queryStr);
}
function remove() {
$db = $this->_dms->getDB();
$db->startTransaction();
$queryStr = "DELETE FROM tblKeywords WHERE category = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$queryStr = "DELETE FROM tblKeywordCategories WHERE id = " . $this->_id;
if (!$db->getResult($queryStr)) {
$db->rollbackTransaction();
return false;
}
$db->commitTransaction();
return true;
}
}
?>

View File

@ -0,0 +1,78 @@
<?php
/**
* Implementation of a notification object
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a notification
*
* @category DMS
* @package SeedDMS_Core
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_Notification { /* {{{ */
/**
* @var integer id of target (document or folder)
*
* @access protected
*/
protected $_target;
/**
* @var integer document or folder
*
* @access protected
*/
protected $_targettype;
/**
* @var integer id of user to notify
*
* @access protected
*/
protected $_userid;
/**
* @var integer id of group to notify
*
* @access protected
*/
protected $_groupid;
/**
* @var object reference to the dms instance this user belongs to
*
* @access protected
*/
protected $_dms;
function SeedDMS_Core_Notification($target, $targettype, $userid, $groupid) { /* {{{ */
$this->_target = $target;
$this->_targettype = $targettype;
$this->_userid = $userid;
$this->_groupid = $groupid;
} /* }}} */
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
function getTarget() { return $this->_target; }
function getTargetType() { return $this->_targettype; }
function getUser() { return $this->_dms->getUser($this->_userid); }
function getGroup() { return $this->_dms->getGroup($this->_groupid); }
} /* }}} */
?>

View File

@ -0,0 +1,162 @@
<?php
/**
* Implementation of an generic object in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @license GPL2
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2012 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a generic object in the document management system
*
* This is the base class for generic objects in SeedDMS.
*
* @category DMS
* @package SeedDMS_Core
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2012 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_Object { /* {{{ */
/**
* @var integer unique id of object
*/
protected $_id;
/**
* @var array list of attributes
*/
protected $_attributes;
/**
* @var object back reference to document management system
*/
public $_dms;
function SeedDMS_Core_Object($id) { /* {{{ */
$this->_id = $id;
$this->_dms = null;
} /* }}} */
/*
* Set dms this object belongs to.
*
* Each object needs a reference to the dms it belongs to. It will be
* set when the object is created.
* The dms has a references to the currently logged in user
* and the database connection.
*
* @param object $dms reference to dms
*/
function setDMS($dms) { /* {{{ */
$this->_dms = $dms;
} /* }}} */
/*
* Return the internal id of the document
*
* @return integer id of document
*/
function getID() { return $this->_id; }
/**
* Returns all attributes set for the object
*
* @return array list of objects of class SeedDMS_Core_Attribute
*/
function getAttributes() { /* {{{ */
if (!$this->_attributes) {
$db = $this->_dms->getDB();
switch(get_class($this)) {
case "SeedDMS_Core_Document":
$queryStr = "SELECT * FROM tblDocumentAttributes WHERE document = " . $this->_id." ORDER BY `id`";
break;
case "SeedDMS_Core_DocumentContent":
$queryStr = "SELECT * FROM tblDocumentContentAttributes WHERE content = " . $this->_id." ORDER BY `id`";
break;
case "SeedDMS_Core_Folder":
$queryStr = "SELECT * FROM tblFolderAttributes WHERE folder = " . $this->_id." ORDER BY `id`";
break;
default:
return false;
}
$resArr = $db->getResultArray($queryStr);
if (is_bool($resArr) && !$resArr) return false;
$this->_attributes = array();
foreach ($resArr as $row) {
$attrdef = $this->_dms->getAttributeDefinition($row['attrdef']);
$attr = new SeedDMS_Core_Attribute($row["id"], $this, $attrdef, $row["value"]);
$attr->setDMS($this->_dms);
$this->_attributes[$attrdef->getId()] = $attr;
}
}
return $this->_attributes;
} /* }}} */
/**
* Returns an attribute of the object for the given attribute definition
*
* @return object object of class SeedDMS_Core_Attribute or false
*/
function getAttributeValue($attrdef) { /* {{{ */
if (!$this->_attributes) {
$this->getAttributes();
}
if (isset($this->_attributes[$attrdef->getId()]))
return $this->_attributes[$attrdef->getId()]->getValue();
else
return false;
} /* }}} */
/**
* Set an attribute of the object for the given attribute definition
*
* @return boolean true if operation was successful, otherwise false
*/
function setAttributeValue($attrdef, $value) { /* {{{ */
$db = $this->_dms->getDB();
if (!$this->_attributes) {
$this->getAttributes();
}
if(!isset($this->_attributes[$attrdef->getId()])) {
switch(get_class($this)) {
case "SeedDMS_Core_Document":
$queryStr = "INSERT INTO tblDocumentAttributes (document, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
break;
case "SeedDMS_Core_DocumentContent":
$queryStr = "INSERT INTO tblDocumentContentAttributes (content, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
break;
case "SeedDMS_Core_Folder":
$queryStr = "INSERT INTO tblFolderAttributes (folder, attrdef, value) VALUES (".$this->_id.", ".$attrdef->getId().", ".$db->qstr($value).")";
break;
default:
return false;
}
$res = $db->getResult($queryStr);
if (!$res)
return false;
$attr = new SeedDMS_Core_Attribute($db->getInsertID(), $this, $attrdef, $value);
$attr->setDMS($this->_dms);
$this->_attributes[$attrdef->getId()] = $attr;
return true;
}
$this->_attributes[$attrdef->getId()]->setValue($value);
return true;
} /* }}} */
} /* }}} */
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
<?php
/**
* Implementation of database access
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe,
* 2010 Matteo Lucarelli, 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Include the adodb database abstraction
*/
require_once "adodb/adodb.inc.php";
/**
* Class to represent the database access for the document management
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Matteo Lucarelli, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal, 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli, 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_DatabaseAccess {
var $_debug;
var $_driver;
var $_hostname;
var $_database;
var $_user;
var $_passw;
var $_conn;
var $_connected;
var $_ttreviewid;
var $_ttapproveid;
var $_ttstatid;
var $_ttcontentid;
var $_intransaction;
/*
Backup functions
*/
/**
* Return list of all database tables
*
* This function is used to retrieve a list of database tables for backup
*
* @return array list of table names
*/
function TableList() {
return $this->_conn->MetaTables("TABLES");
}
/**
* Constructor of SeedDMS_Core_DatabaseAccess
*
* Sets all database parameters but does not connect.
*
* @param string $driver the database type e.g. mysql, sqlite
* @param string $hostname host of database server
* @param string $user name of user having access to database
* @param string $passw password of user
* @param string $database name of database
*/
function SeedDMS_Core_DatabaseAccess($driver, $hostname, $user, $passw, $database = false) {
$this->_driver = $driver;
$this->_hostname = $hostname;
$this->_database = $database;
$this->_user = $user;
$this->_passw = $passw;
$this->_connected = false;
$this->_intransaction = 0;
// $tt*****id is a hack to ensure that we do not try to create the
// temporary table twice during a single connection. Can be fixed by
// using Views (MySQL 5.0 onward) instead of temporary tables.
// CREATE ... IF NOT EXISTS cannot be used because it has the
// unpleasant side-effect of performing the insert again even if the
// table already exists.
//
// See createTemporaryTable() method for implementation.
$this->_ttreviewid = false;
$this->_ttapproveid = false;
$this->_ttstatid = false;
$this->_ttcontentid = false;
$this->_debug = false;
}
/**
* Connect to database
*
* @return boolean true if connection could be established, otherwise false
*/
function connect() { /* {{{ */
$this->_conn = ADONewConnection($this->_driver);
if ($this->_database)
$this->_conn->Connect($this->_hostname, $this->_user, $this->_passw, $this->_database);
else
$this->_conn->Connect($this->_hostname, $this->_user, $this->_passw);
if (!$this->_conn)
return false;
$this->_conn->SetFetchMode(ADODB_FETCH_ASSOC);
$this->_conn->Execute('SET NAMES utf8');
$this->_connected = true;
return true;
} /* }}} */
/**
* Make sure a database connection exisits
*
* This function checks for a database connection. If it does not exists
* it will reconnect.
*
* @return boolean true if connection is established, otherwise false
*/
function ensureConnected() { /* {{{ */
if (!$this->_connected) return $this->connect();
else return true;
} /* }}} */
/**
* Sanitize String used in database operations
*
* @param string text
* @return string sanitized string
*/
function qstr($text) { /* {{{ */
return $this->_conn->qstr($text);
} /* }}} */
/**
* Execute SQL query and return result
*
* Call this function only with sql query which return data records.
*
* @param string $queryStr sql query
* @return array/boolean data if query could be executed otherwise false
*/
function getResultArray($queryStr) { /* {{{ */
$resArr = array();
$res = $this->_conn->Execute($queryStr);
if (!$res) {
if($this->_debug)
echo "error: ".$queryStr."<br />";
return false;
}
$resArr = $res->GetArray();
$res->Close();
return $resArr;
} /* }}} */
/**
* Execute SQL query
*
* Call this function only with sql query which do not return data records.
*
* @param string $queryStr sql query
* @param boolean $silent not used anymore. This was used when this method
* still issued an error message
* @return boolean true if query could be executed otherwise false
*/
function getResult($queryStr, $silent=false) { /* {{{ */
$res = $this->_conn->Execute($queryStr);
if(!$res) {
if($this->_debug)
echo "error: ".$queryStr."<br />";
}
return $res;
} /* }}} */
/**
* Return the id of the last instert record
*
* @return integer id used in last autoincrement
*/
function getInsertID() { /* {{{ */
return $this->_conn->Insert_ID();
} /* }}} */
function startTransaction() { /* {{{ */
if(!$this->_intransaction) {
$this->_conn->BeginTrans();
}
$this->_intransaction++;
} /* }}} */
function rollbackTransaction() { /* {{{ */
if($this->_intransaction == 1) {
$this->_conn->RollbackTrans();
}
$this->_intransaction--;
} /* }}} */
function commitTransaction() { /* {{{ */
if($this->_intransaction == 1) {
$this->_conn->CommitTrans();
}
$this->_intransaction--;
} /* }}} */
function getErrorMsg() { /* {{{ */
return $this->_conn->ErrorMsg();
} /* }}} */
function getErrorNo() { /* {{{ */
return $this->_conn->ErrorNo();
} /* }}} */
/**
* Create various temporary tables to speed up and simplify sql queries
*/
function createTemporaryTable($tableName, $override=false) { /* {{{ */
if (!strcasecmp($tableName, "ttreviewid")) {
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
"FROM `tblDocumentReviewLog` ".
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
if (!$this->_ttreviewid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttreviewid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttreviewid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttreviewid;
}
else if (!strcasecmp($tableName, "ttapproveid")) {
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentApproveLog`.`approveID`, ".
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
"FROM `tblDocumentApproveLog` ".
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
if (!$this->_ttapproveid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttapproveid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttapproveid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttapproveid;
}
else if (!strcasecmp($tableName, "ttstatid")) {
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentStatusLog`.`statusID`, ".
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
"FROM `tblDocumentStatusLog` ".
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
if (!$this->_ttstatid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttstatid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttstatid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttstatid;
}
else if (!strcasecmp($tableName, "ttcontentid")) {
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ".
"SELECT `tblDocumentContent`.`document`, ".
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
"FROM `tblDocumentContent` ".
"GROUP BY `tblDocumentContent`.`document` ".
"ORDER BY `tblDocumentContent`.`document`";
if (!$this->_ttcontentid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttcontentid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttcontentid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttcontentid;
}
return false;
} /* }}} */
}
?>

View File

@ -0,0 +1,423 @@
<?php
/**
* Implementation of database access using PDO
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2012 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent the database access for the document management
* This class uses PDO for the actual database access.
*
* @category DMS
* @package SeedDMS_Core
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2012 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_DatabaseAccess {
/**
* @var boolean set to true for debug mode
*/
public $_debug;
/**
* @var string name of database driver (mysql or sqlite3)
*/
protected $_driver;
/**
* @var string name of hostname
*/
protected $_hostname;
/**
* @var string name of database
*/
protected $_database;
/**
* @var string name of database user
*/
protected $_user;
/**
* @var string password of database user
*/
protected $_passw;
/**
* @var object internal database connection
*/
private $_conn;
/**
* @var boolean set to true if connection to database is established
*/
private $_connected;
/**
* @var boolean set to true if temp. table for tree view has been created
*/
private $_ttreviewid;
/**
* @var boolean set to true if temp. table for approvals has been created
*/
private $_ttapproveid;
/**
* @var boolean set to true if temp. table for doc status has been created
*/
private $_ttstatid;
/**
* @var boolean set to true if temp. table for doc content has been created
*/
private $_ttcontentid;
/**
* @var boolean set to true if in a database transaction
*/
private $_intransaction;
/**
* Return list of all database tables
*
* This function is used to retrieve a list of database tables for backup
*
* @return array list of table names
*/
function TableList() { /* {{{ */
switch($this->_driver) {
case 'mysql':
$sql = "select TABLE_NAME as name from information_schema.tables where TABLE_SCHEMA='".$this->_database."' and TABLE_TYPE='BASE TABLE'";
break;
case 'sqlite':
$sql = "select tbl_name as name from sqlite_master where type='table'";
break;
default:
return false;
}
$arr = $this->getResultArray($sql);
$res = array();
foreach($arr as $tmp)
$res[] = $tmp['name'];
return $res;
} /* }}} */
/**
* Constructor of SeedDMS_Core_DatabaseAccess
*
* Sets all database parameters but does not connect.
*
* @param string $driver the database type e.g. mysql, sqlite
* @param string $hostname host of database server
* @param string $user name of user having access to database
* @param string $passw password of user
* @param string $database name of database
*/
function SeedDMS_Core_DatabaseAccess($driver, $hostname, $user, $passw, $database = false) { /* {{{ */
$this->_driver = $driver;
$this->_hostname = $hostname;
$this->_database = $database;
$this->_user = $user;
$this->_passw = $passw;
$this->_connected = false;
// $tt*****id is a hack to ensure that we do not try to create the
// temporary table twice during a single connection. Can be fixed by
// using Views (MySQL 5.0 onward) instead of temporary tables.
// CREATE ... IF NOT EXISTS cannot be used because it has the
// unpleasant side-effect of performing the insert again even if the
// table already exists.
//
// See createTemporaryTable() method for implementation.
$this->_ttreviewid = false;
$this->_ttapproveid = false;
$this->_ttstatid = false;
$this->_ttcontentid = false;
$this->_debug = false;
} /* }}} */
/**
* Connect to database
*
* @return boolean true if connection could be established, otherwise false
*/
function connect() { /* {{{ */
switch($this->_driver) {
case 'mysql':
case 'mysqli':
case 'mysqlnd':
$dsn = $this->_driver.":dbname=".$this->_database.";host=".$this->_hostname;
break;
case 'sqlite':
$dsn = $this->_driver.":".$this->_database;
break;
}
$this->_conn = new PDO($dsn, $this->_user, $this->_passw);
if (!$this->_conn)
return false;
switch($this->_driver) {
case 'mysql':
$this->_conn->exec('SET NAMES utf8');
break;
}
$this->_connected = true;
return true;
} /* }}} */
/**
* Make sure a database connection exisits
*
* This function checks for a database connection. If it does not exists
* it will reconnect.
*
* @return boolean true if connection is established, otherwise false
*/
function ensureConnected() { /* {{{ */
if (!$this->_connected) return $this->connect();
else return true;
} /* }}} */
/**
* Sanitize String used in database operations
*
* @param string text
* @return string sanitized string
*/
function qstr($text) { /* {{{ */
return $this->_conn->quote($text);
} /* }}} */
/**
* Execute SQL query and return result
*
* Call this function only with sql query which return data records.
*
* @param string $queryStr sql query
* @return array/boolean data if query could be executed otherwise false
*/
function getResultArray($queryStr) { /* {{{ */
$resArr = array();
$res = $this->_conn->query($queryStr);
if ($res === false) {
if($this->_debug)
echo "error: ".$queryStr."<br />";
return false;
}
$resArr = $res->fetchAll(PDO::FETCH_ASSOC);
// $res->Close();
return $resArr;
} /* }}} */
/**
* Execute SQL query
*
* Call this function only with sql query which do not return data records.
*
* @param string $queryStr sql query
* @param boolean $silent not used anymore. This was used when this method
* still issued an error message
* @return boolean true if query could be executed otherwise false
*/
function getResult($queryStr, $silent=false) { /* {{{ */
$res = $this->_conn->exec($queryStr);
if($res === false) {
if($this->_debug)
echo "error: ".$queryStr."<br />";
return false;
} else
return true;
return $res;
} /* }}} */
function startTransaction() { /* {{{ */
if(!$this->_intransaction) {
$this->_conn->beginTransaction();
}
$this->_intransaction++;
} /* }}} */
function rollbackTransaction() { /* {{{ */
if($this->_intransaction == 1) {
$this->_conn->rollBack();
}
$this->_intransaction--;
} /* }}} */
function commitTransaction() { /* {{{ */
if($this->_intransaction == 1) {
$this->_conn->commit();
}
$this->_intransaction--;
} /* }}} */
/**
* Return the id of the last instert record
*
* @return integer id used in last autoincrement
*/
function getInsertID() { /* {{{ */
return $this->_conn->lastInsertId();
} /* }}} */
function getErrorMsg() { /* {{{ */
$info = $this->_conn->errorInfo();
return($info[2]);
} /* }}} */
function getErrorNo() { /* {{{ */
return $this->_conn->errorCode();
} /* }}} */
/**
* Create various temporary tables to speed up and simplify sql queries
*/
function createTemporaryTable($tableName, $override=false) { /* {{{ */
if (!strcasecmp($tableName, "ttreviewid")) {
switch($this->_driver) {
case 'sqlite':
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` AS ".
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
"FROM `tblDocumentReviewLog` ".
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
break;
default:
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttreviewid` (PRIMARY KEY (`reviewID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentReviewLog`.`reviewID`, ".
"MAX(`tblDocumentReviewLog`.`reviewLogID`) AS `maxLogID` ".
"FROM `tblDocumentReviewLog` ".
"GROUP BY `tblDocumentReviewLog`.`reviewID` ".
"ORDER BY `tblDocumentReviewLog`.`reviewLogID`";
}
if (!$this->_ttreviewid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttreviewid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttreviewid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttreviewid;
}
else if (!strcasecmp($tableName, "ttapproveid")) {
switch($this->_driver) {
case 'sqlite':
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` AS ".
"SELECT `tblDocumentApproveLog`.`approveID`, ".
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
"FROM `tblDocumentApproveLog` ".
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
break;
default:
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttapproveid` (PRIMARY KEY (`approveID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentApproveLog`.`approveID`, ".
"MAX(`tblDocumentApproveLog`.`approveLogID`) AS `maxLogID` ".
"FROM `tblDocumentApproveLog` ".
"GROUP BY `tblDocumentApproveLog`.`approveID` ".
"ORDER BY `tblDocumentApproveLog`.`approveLogID`";
}
if (!$this->_ttapproveid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttapproveid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttapproveid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttapproveid;
}
else if (!strcasecmp($tableName, "ttstatid")) {
switch($this->_driver) {
case 'sqlite':
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` AS ".
"SELECT `tblDocumentStatusLog`.`statusID` AS `statusID`, ".
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
"FROM `tblDocumentStatusLog` ".
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
break;
default:
$queryStr = "CREATE TEMPORARY TABLE IF NOT EXISTS `ttstatid` (PRIMARY KEY (`statusID`), INDEX (`maxLogID`)) ".
"SELECT `tblDocumentStatusLog`.`statusID`, ".
"MAX(`tblDocumentStatusLog`.`statusLogID`) AS `maxLogID` ".
"FROM `tblDocumentStatusLog` ".
"GROUP BY `tblDocumentStatusLog`.`statusID` ".
"ORDER BY `tblDocumentStatusLog`.`statusLogID`";
}
if (!$this->_ttstatid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttstatid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttstatid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttstatid;
}
else if (!strcasecmp($tableName, "ttcontentid")) {
switch($this->_driver) {
case 'sqlite':
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` AS ".
"SELECT `tblDocumentContent`.`document` AS `document`, ".
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
"FROM `tblDocumentContent` ".
"GROUP BY `tblDocumentContent`.`document` ".
"ORDER BY `tblDocumentContent`.`document`";
break;
default:
$queryStr = "CREATE TEMPORARY TABLE `ttcontentid` (PRIMARY KEY (`document`), INDEX (`maxVersion`)) ".
"SELECT `tblDocumentContent`.`document`, ".
"MAX(`tblDocumentContent`.`version`) AS `maxVersion` ".
"FROM `tblDocumentContent` ".
"GROUP BY `tblDocumentContent`.`document` ".
"ORDER BY `tblDocumentContent`.`document`";
}
if (!$this->_ttcontentid) {
if (!$this->getResult($queryStr))
return false;
$this->_ttcontentid=true;
}
else {
if (is_bool($override) && $override) {
if (!$this->getResult("DELETE FROM `ttcontentid`"))
return false;
if (!$this->getResult($queryStr))
return false;
}
}
return $this->_ttcontentid;
}
return false;
} /* }}} */
}
?>

View File

@ -0,0 +1,218 @@
<?php
/**
* Implementation of various file system operations
*
* @category DMS
* @package SeedDMS_Core
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal,
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class to represent a user in the document management system
*
* @category DMS
* @package SeedDMS_Core
* @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2002-2005 Markus Westphal,
* 2006-2008 Malcolm Cowe, 2010 Matteo Lucarelli,
* 2010 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Core_File {
function renameFile($old, $new) { /* {{{ */
return @rename($old, $new);
} /* }}} */
function removeFile($file) { /* {{{ */
return @unlink($file);
} /* }}} */
function copyFile($source, $target) { /* {{{ */
return @copy($source, $target);
} /* }}} */
function moveFile($source, $target) { /* {{{ */
if (!@copyFile($source, $target))
return false;
return @removeFile($source);
} /* }}} */
function fileSize($file) { /* {{{ */
if(!$a = fopen($file, 'r'))
return false;
fseek($a, 0, SEEK_END);
$filesize = ftell($a);
fclose($a);
return $filesize;
} /* }}} */
function format_filesize($size, $sizes = array('Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB')) { /* {{{ */
if ($size == 0) return('0 Bytes');
return (round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $sizes[$i]);
} /* }}} */
function parse_filesize($str) { /* {{{ */
preg_replace('/\s\s+/', ' ', $str);
if(strtoupper(substr($str, -1)) == 'B') {
$value = (int) substr($str, 0, -2);
$unit = substr($str, -2, 1);
} else {
$value = (int) substr($str, 0, -1);
$unit = substr($str, -1);
}
switch(strtoupper($unit)) {
case 'G':
return $value * 1024 * 1024 * 1024;
break;
case 'M':
return $value * 1024 * 1024;
break;
case 'K':
return $value * 1024;
break;
default;
return $value;
break;
}
return false;
} /* }}} */
function checksum($file) { /* {{{ */
return md5_file($file);
} /* }}} */
function renameDir($old, $new) { /* {{{ */
return @rename($old, $new);
} /* }}} */
function makeDir($path) { /* {{{ */
if( !is_dir( $path ) ){
$res=@mkdir( $path , 0777, true);
if (!$res) return false;
}
return true;
/* some old code
if (strncmp($path, DIRECTORY_SEPARATOR, 1) == 0) {
$mkfolder = DIRECTORY_SEPARATOR;
}
else {
$mkfolder = "";
}
$path = preg_split( "/[\\\\\/]/" , $path );
for( $i=0 ; isset( $path[$i] ) ; $i++ )
{
if(!strlen(trim($path[$i])))continue;
$mkfolder .= $path[$i];
if( !is_dir( $mkfolder ) ){
$res=@mkdir( "$mkfolder" , 0777);
if (!$res) return false;
}
$mkfolder .= DIRECTORY_SEPARATOR;
}
return true;
// patch from alekseynfor safe_mod or open_basedir
global $settings;
$path = substr_replace ($path, "/", 0, strlen($settings->_contentDir));
$mkfolder = $settings->_contentDir;
$path = preg_split( "/[\\\\\/]/" , $path );
for( $i=0 ; isset( $path[$i] ) ; $i++ )
{
if(!strlen(trim($path[$i])))continue;
$mkfolder .= $path[$i];
if( !is_dir( $mkfolder ) ){
$res= @mkdir( "$mkfolder" , 0777);
if (!$res) return false;
}
$mkfolder .= DIRECTORY_SEPARATOR;
}
return true;
*/
} /* }}} */
function removeDir($path) { /* {{{ */
$handle = @opendir($path);
while ($entry = @readdir($handle) )
{
if ($entry == ".." || $entry == ".")
continue;
else if (is_dir($path . $entry))
{
if (!self::removeDir($path . $entry . "/"))
return false;
}
else
{
if (!@unlink($path . $entry))
return false;
}
}
@closedir($handle);
return @rmdir($path);
} /* }}} */
function copyDir($sourcePath, $targetPath) { /* {{{ */
if (mkdir($targetPath, 0777)) {
$handle = @opendir($sourcePath);
while ($entry = @readdir($handle) ) {
if ($entry == ".." || $entry == ".")
continue;
else if (is_dir($sourcePath . $entry)) {
if (!self::copyDir($sourcePath . $entry . "/", $targetPath . $entry . "/"))
return false;
} else {
if (!@copy($sourcePath . $entry, $targetPath . $entry))
return false;
}
}
@closedir($handle);
}
else
return false;
return true;
} /* }}} */
function moveDir($sourcePath, $targetPath) { /* {{{ */
if (!copyDir($sourcePath, $targetPath))
return false;
return removeDir($sourcePath);
} /* }}} */
// code by Kioob (php.net manual)
function gzcompressfile($source,$level=false) { /* {{{ */
$dest=$source.'.gz';
$mode='wb'.$level;
$error=false;
if($fp_out=@gzopen($dest,$mode)) {
if($fp_in=@fopen($source,'rb')) {
while(!feof($fp_in))
@gzwrite($fp_out,fread($fp_in,1024*512));
@fclose($fp_in);
}
else $error=true;
@gzclose($fp_out);
}
else $error=true;
if($error) return false;
else return $dest;
} /* }}} */
}
?>

421
SeedDMS_Core/package.xml Normal file
View File

@ -0,0 +1,421 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>SeedDMS_Core</name>
<channel>pear.php.net</channel>
<summary>Document management system</summary>
<description>SeedDMS is a web based document management system (DMS). This is
the core of it, providing the basic functionality to create/update and delete
folders and documents. It also contains a user and group managment</description>
<lead>
<name>Uwe Steinmann</name>
<user>steinm</user>
<email>uwe@steinmann.cx</email>
<active>yes</active>
</lead>
<date>2013-02-26</date>
<time>15:04:08</time>
<version>
<release>4.0.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- minor bugfixes
</notes>
<contents>
<dir baseinstalldir="SeedDMS" name="/">
<dir name="Core">
<file name="inc.ClassDocument.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassFolder.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassDMS.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassUser.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassGroup.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.DBAccess.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.DBAccessPDO.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.AccessUtils.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.FileUtils.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassAccess.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassKeywords.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassNotification.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassDocumentCategory.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassObject.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassAttribute.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="inc.ClassWorkflow.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /DTD -->
<dir name="tests">
<file name="getfoldertree.php" role="test" />
<file name="getusers.php" role="test" />
</dir> <!-- /tests -->
<file name="Core.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>4.3.0</min>
</php>
<pearinstaller>
<min>1.5.4</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>3.0.0</release>
<api>3.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2010-04-27</date>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
Initial release
</notes>
</release>
<release>
<version>
<release>3.2.0</release>
<api>3.2.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2011-07-23</date>
<time>08:05:38</time>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
New release
</notes>
</release>
<release>
<date>2012-02-08</date>
<time>08:05:38</time>
<version>
<release>3.3.0</release>
<api>3.3.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- added methods to find and repair errors in document and folder records
- removed sendmail parameter from some methods in LetoDMS_Core_Document
- do not use some of the temporay tables anymore
- SetFetchMode(ADODB_FETCH_ASSOC) in LetoDMS_Core_DatabaseAccess::connect()
</notes>
</release>
<release>
<date>2012-03-21</date>
<time>07:39:48</time>
<version>
<release>3.3.1</release>
<api>3.3.1</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- new release
</notes>
</release>
<release>
<date>2012-03-22</date>
<time>08:07:42</time>
<version>
<release>3.3.2</release>
<api>3.3.2</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- fixed bug in LetoDMS_Core_Document::getDir()
</notes>
</release>
<release>
<date>2012-03-28</date>
<time>08:42:35</time>
<version>
<release>3.3.3</release>
<api>3.3.3</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- fixed bug in LetoDMS_Core_Document::getPath()
</notes>
</release>
<release>
<date>2012-04-11</date>
<time>13:34:30</time>
<version>
<release>3.3.4</release>
<api>3.3.4</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- fixed bug in LetoDMS_Core_DocumentFile::getPath()
</notes>
</release>
<release>
<date>2012-04-30</date>
<time>17:11:05</time>
<version>
<release>3.3.5</release>
<api>3.3.5</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- minor corrections
</notes>
</release>
<release>
<date>2012-07-16</date>
<time>16:04:58</time>
<version>
<release>3.3.6</release>
<api>3.3.6</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- no changes, just keep same version as letodms application
</notes>
</release>
<release>
<date>2012-08-25</date>
<time>22:07:58</time>
<version>
<release>3.3.7</release>
<api>3.3.7</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- no changes, just keep same version as letodms application
</notes>
</release>
<release>
<date>2012-09-16</date>
<time>22:14:08</time>
<version>
<release>3.3.8</release>
<api>3.3.8</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- more sql injection protection in LetoDMS_Core_User
</notes>
</release>
<release>
<date>2012-09-19</date>
<time>08:43:18</time>
<version>
<release>3.3.9</release>
<api>3.3.9</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- version update to be in sync with letodms application
</notes>
</release>
<release>
<date>2012-12-13</date>
<time>08:02:34</time>
<version>
<release>3.4.0</release>
<api>3.4.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- added PDO database driver, several sql changes for better compatiblity
- fixed bug when adding a new document category
- make sure the database remains consistent even in case of errors
</notes>
</release>
<release>
<date>2013-01-24</date>
<time>08:02:34</time>
<version>
<release>4.0.0pre1</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- added database transactions
- new workflow
- replaced old var declaration
</notes>
</release>
<release>
<date>2013-02-06</date>
<time>08:02:34</time>
<version>
<release>4.0.0pre2</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- lots of bug fixes
- replaced more of old var declaration
- more code documentation
</notes>
</release>
<release>
<date>2013-02-08</date>
<time>08:02:34</time>
<version>
<release>4.0.0pre3</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- minor bug fixes
</notes>
</release>
<release>
<date>2013-02-11</date>
<time>15:04:08</time>
<version>
<release>4.0.0pre4</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- calculate checksum for document versions
- some bug fixes
- some more documentation
- added new methods SeedDMS_Core_Document::getReadUserList() and
SeedDMS_Core_Folder::getReadUserList() which replaces getApproversList()
- fixed sql statement in getReadUserList() for sqlite3
</notes>
</release>
<release>
<date>2013-02-14</date>
<time>17:36:08</time>
<version>
<release>4.0.0pre5</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- changed name from letodms to seeddms
- fixed SeedDMS_Database::TableList()
</notes>
</release>
<release>
<date>2013-02-20</date>
<time>17:36:08</time>
<version>
<release>4.0.0RC1</release>
<api>4.0.0</api>
</version>
<stability>
<release>beta</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- minor bugfixes
</notes>
</release>
</changelog>
</package>

View File

@ -0,0 +1,10 @@
<?php
$g_config['type'] = 'mysql';
$g_config['hostname'] = 'localhost';
$g_config['user'] = 'letodms';
$g_config['passwd'] = 'letodms';
$g_config['name'] = 'letodms';
$g_config['contentDir'] = '/tmp/content';
$g_config['contentOffsetDir'] = '/tmp/content';
?>

View File

@ -0,0 +1,25 @@
<?php
include("config.php");
include("SeedDMS/SeedDMS_Core.php");
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
function tree($folder, $indent='') {
echo $indent."D ".$folder->getName()."\n";
$subfolders = $folder->getSubFolders();
foreach($subfolders as $subfolder) {
tree($subfolder, $indent.' ');
}
$documents = $folder->getDocuments();
foreach($documents as $document) {
echo $indent." ".$document->getName()."\n";
}
}
$folder = $dms->getFolder(1);
tree($folder);
?>

View File

@ -0,0 +1,14 @@
<?php
include("config.php");
include("SeedDMS/SeedDMS_Core.php");
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
$users = $dms->getAllUsers();
foreach($users as $user)
echo $user->getId()." ".$user->getLogin()." ".$user->getFullname()."\n";
?>

View File

@ -0,0 +1,44 @@
<?php
include("config.php");
include("SeedDMS/SeedDMS_Core.php");
$db = new SeedDMS_Core_DatabaseAccess($g_config['type'], $g_config['hostname'], $g_config['user'], $g_config['passwd'], $g_config['name']);
$db->connect() or die ("Could not connect to db-server \"" . $g_config['hostname'] . "\"");
$dms = new SeedDMS_Core_DMS($db, $g_config['contentDir'], $g_config['contentOffsetDir']);
$path = '/Test 1/';
echo "Searching for folder or document with path '".$path."'\n";
$root = $dms->getRootFolder();
if($path[0] == '/') {
$path = substr($path, 1);
}
$patharr = explode('/', $path);
/* The last entry is always the document, though if the path ends in '/' the
* document name will be empty.
*/
$docname = array_pop($patharr);
$parentfolder = $root;
foreach($patharr as $pathseg) {
if($folder = $dms->getFolderByName($pathseg, $parentfolder)) {
$parentfolder = $folder;
}
}
if($folder) {
if($docname) {
if($document = $dms->getDocumentByName($docname, $folder)) {
echo "Given path is document '".$document->getName()."'\n";
} else {
echo "No object found\n";
}
} else {
echo "Given path is a folder '".$folder->getName()."'\n";
}
} else {
echo "No object found\n";
}
?>

44
SeedDMS_Lucene/Lucene.php Normal file
View File

@ -0,0 +1,44 @@
<?php
// SeedDMS. Document Management System
// Copyright (C) 2011-2013 Uwe Steinmann
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// 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, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
/**
* @uses Zend_Search_Lucene
*/
require_once('Zend/Search/Lucene.php');
/**
* @uses Zend_Search_Lucene_Analysis_TokenFilter_Stopwords
*/
require_once("Zend/Search/Lucene/Analysis/TokenFilter/StopWords.php");
/**
* @uses SeedDMS_Lucene_Indexer
*/
require_once('Lucene/Indexer.php');
/**
* @uses SeedDMS_Lucene_Search
*/
require_once('Lucene/Search.php');
/**
* @uses SeedDMS_Lucene_IndexedDocument
*/
require_once('Lucene/IndexedDocument.php');
?>

View File

@ -0,0 +1,108 @@
<?php
/**
* Implementation of an indexed document
*
* @category DMS
* @package SeedDMS_Lucene
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010, Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class for managing an indexed document.
*
* @category DMS
* @package SeedDMS_Lucene
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2011, Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Lucene_IndexedDocument extends Zend_Search_Lucene_Document {
/**
* Constructor. Creates our indexable document and adds all
* necessary fields to it using the passed in document
*/
public function __construct($dms, $document, $convcmd=null, $nocontent=false) {
$_convcmd = array(
'application/pdf' => 'pdftotext -enc UTF-8 -nopgbrk %s - |sed -e \'s/ [a-zA-Z0-9.]\{1\} / /g\' -e \'s/[0-9.]//g\'',
'application/msword' => 'catdoc %s',
'application/vnd.ms-excel' => 'ssconvert -T Gnumeric_stf:stf_csv -S %s fd://1',
'audio/mp3' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
'audio/mpeg' => "id3 -l -R %s | egrep '(Title|Artist|Album)' | sed 's/^[^:]*: //g'",
'text/plain' => 'cat %s',
);
if($convcmd) {
$_convcmd = $convcmd;
}
$version = $document->getLatestContent();
$this->addField(Zend_Search_Lucene_Field::Keyword('document_id', $document->getID()));
if($version) {
$this->addField(Zend_Search_Lucene_Field::Keyword('mimetype', $version->getMimeType()));
$this->addField(Zend_Search_Lucene_Field::Keyword('origfilename', $version->getOriginalFileName()));
if(!$nocontent)
$this->addField(Zend_Search_Lucene_Field::UnIndexed('created', $version->getDate()));
if($attributes = $version->getAttributes()) {
foreach($attributes as $attribute) {
$attrdef = $attribute->getAttributeDefinition();
if($attrdef->getValueSet() != '')
$this->addField(Zend_Search_Lucene_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
else
$this->addField(Zend_Search_Lucene_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
}
}
}
$this->addField(Zend_Search_Lucene_Field::Text('title', $document->getName()));
if($categories = $document->getCategories()) {
$names = array();
foreach($categories as $cat) {
$names[] = $cat->getName();
}
$this->addField(Zend_Search_Lucene_Field::Text('category', implode(' ', $names)));
}
if($attributes = $document->getAttributes()) {
foreach($attributes as $attribute) {
$attrdef = $attribute->getAttributeDefinition();
if($attrdef->getValueSet() != '')
$this->addField(Zend_Search_Lucene_Field::Keyword('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
else
$this->addField(Zend_Search_Lucene_Field::Text('attr_'.str_replace(' ', '_', $attrdef->getName()), $attribute->getValue()));
}
}
$owner = $document->getOwner();
$this->addField(Zend_Search_Lucene_Field::Text('owner', $owner->getLogin()));
if($keywords = $document->getKeywords()) {
$this->addField(Zend_Search_Lucene_Field::Text('keywords', $keywords));
}
if($comment = $document->getComment()) {
$this->addField(Zend_Search_Lucene_Field::Text('comment', $comment));
}
if($version && !$nocontent) {
$path = $dms->contentDir . $version->getPath();
$content = '';
$fp = null;
$mimetype = $version->getMimeType();
if(isset($_convcmd[$mimetype])) {
$cmd = sprintf($_convcmd[$mimetype], $path);
$fp = popen($cmd, 'r');
if($fp) {
$content = '';
while(!feof($fp)) {
$content .= fread($fp, 2048);
}
pclose($fp);
}
if($content) {
$this->addField(Zend_Search_Lucene_Field::UnStored('content', $content, 'utf-8'));
}
}
}
}
}
?>

View File

@ -0,0 +1,63 @@
<?php
/**
* Implementation of lucene index
*
* @category DMS
* @package SeedDMS_Lucene
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010, Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class for managing a lucene index.
*
* @category DMS
* @package SeedDMS_Lucene
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2011, Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Lucene_Indexer {
/**
* @var string $indexname name of lucene index
* @access protected
*/
protected $indexname;
function open($luceneDir) { /* {{{ */
try {
$index = Zend_Search_Lucene::open($luceneDir);
return($index);
} catch (Exception $e) {
return null;
}
} /* }}} */
function create($luceneDir) { /* {{{ */
$index = Zend_Search_Lucene::create($luceneDir);
return($index);
} /* }}} */
/**
* Do some initialization
*
*/
function init($stopWordsFile='') { /* {{{ */
$analyzer = new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive();
if($stopWordsFile && file_exists($stopWordsFile)) {
$stopWordsFilter = new Zend_Search_Lucene_Analysis_TokenFilter_StopWords();
$stopWordsFilter->loadFromFile($stopWordsFile);
$analyzer->addFilter($stopWordsFilter);
}
Zend_Search_Lucene_Analysis_Analyzer::setDefault($analyzer);
} /* }}} */
}
?>

View File

@ -0,0 +1,78 @@
<?php
/**
* Implementation of search in lucene index
*
* @category DMS
* @package SeedDMS_Lucene
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010, Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class for searching in a lucene index.
*
* @category DMS
* @package SeedDMS_Lucene
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2011, Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Lucene_Search {
/**
* @var object $index lucene index
* @access protected
*/
protected $index;
/**
* Create a new instance of the search
*
* @param object $index lucene index
* @return object instance of SeedDMS_Lucene_Search
*/
function __construct($index) { /* {{{ */
$this->index = $index;
$this->version = '@package_version@';
if($this->version[0] == '@')
$this->version = '3.0.0';
} /* }}} */
/**
* Search in index
*
* @param object $index lucene index
* @return object instance of SeedDMS_Lucene_Search
*/
function search($term, $owner, $status='', $categories=array(), $fields=array()) { /* {{{ */
$query = '';
if($fields) {
} else {
if($term)
$query .= trim($term);
}
if($owner) {
if($query)
$query .= ' && ';
$query .= 'owner:'.$owner;
}
if($categories) {
if($query)
$query .= ' && ';
$query .= '(category:"';
$query .= implode('" || category:"', $categories);
$query .= '")';
}
$hits = $this->index->find($query);
$recs = array();
foreach($hits as $hit) {
$recs[] = array('id'=>$hit->id, 'document_id'=>$hit->document_id);
}
return $recs;
} /* }}} */
}
?>

108
SeedDMS_Lucene/package.xml Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>SeedDMS_Lucene</name>
<channel>pear.php.net</channel>
<summary>Fulltext search for SeedDMS</summary>
<description>SeedDMS is a web based document management system (DMS). This is
the fulltext search engine for it, based on Lucene.</description>
<lead>
<name>Uwe Steinmann</name>
<user>steinm</user>
<email>uwe@steinmann.cx</email>
<active>yes</active>
</lead>
<date>2012-12-03</date>
<time>10:31:23</time>
<version>
<release>1.1.1</release>
<api>1.1.1</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
catch exception if index is opened but not available
</notes>
<contents>
<dir baseinstalldir="SeedDMS" name="/">
<dir name="Lucene">
<file name="Indexer.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="Search.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="IndexedDocument.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /Lucene -->
<dir name="tests">
</dir> <!-- /tests -->
<file name="Lucene.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>4.3.0</min>
</php>
<pearinstaller>
<min>1.5.4</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
<version>
<release>0.0.1</release>
<api>0.0.1</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-04-27</date>
<license uri="http://opensource.org/licenses/bsd-license">BSD License</license>
<notes>
</notes>
</release>
<release>
<date>2011-11-06</date>
<time>08:05:38</time>
<version>
<release>1.0.1</release>
<api>1.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
- New Release
</notes>
</release>
<release>
<date>2012-11-06</date>
<time>08:05:38</time>
<version>
<release>1.1.0</release>
<api>1.1.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
use a configurable list of mime type converters, fixed indexing and searching
of special chars like german umlaute.
</notes>
</release>
</changelog>
</package>

View File

@ -0,0 +1,24 @@
<?php
// SeedDMS. Document Management System
// Copyright (C) 2011-2013 Uwe Steinmann
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// 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, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
/**
* @uses Preview/Previewer.php
*/
require_once('Preview/Previewer.php');
?>

View File

@ -0,0 +1,134 @@
<?php
/**
* Implementation of preview documents
*
* @category DMS
* @package SeedDMS_Preview
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010, Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class for managing creation of preview images for documents.
*
* @category DMS
* @package SeedDMS_Preview
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2011, Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Preview_Previewer {
/**
* @var string $cacheDir location in the file system where all the
* cached data like thumbnails are located. This should be an
* absolute path.
* @access public
*/
public $previewDir;
/**
* @var integer $width maximum width/height of resized image
* @access protected
*/
protected $width;
function __construct($previewDir, $width=40) {
if(!is_dir($previewDir)) {
if (!SeedDMS_Core_File::makeDir($previewDir)) {
$this->previewDir = '';
} else {
$this->previewDir = $previewDir;
}
} else {
$this->previewDir = $previewDir;
}
$this->width = intval($width);
}
function createPreview($documentcontent, $width=0) { /* {{{ */
if($width == 0)
$width = $this->width;
else
$width = intval($width);
if(!$this->previewDir)
return false;
$document = $documentcontent->getDocument();
$dir = $this->previewDir.'/'.$document->getDir();
if(!is_dir($dir)) {
if (!SeedDMS_Core_File::makeDir($dir)) {
return false;
}
}
$file = $document->_dms->contentDir.$documentcontent->getPath();
if(!file_exists($file))
return false;
$target = $dir.'p'.$documentcontent->getVersion().'-'.$width.'.png';
if(!file_exists($target)) {
$cmd = '';
switch($documentcontent->getMimeType()) {
case "image/png":
case "image/gif":
case "image/jpeg":
case "image/jpg":
$cmd = 'convert -resize '.$width.'x'.$width.' '.$file.' '.$target;
break;
case "application/pdf":
$cmd = 'convert -density 18 -resize '.$width.'x'.$width.' '.$file.'[0] '.$target;
}
if($cmd) {
system( $cmd);
}
return true;
}
return true;
} /* }}} */
function hasPreview($documentcontent, $width=0) { /* {{{ */
if($width == 0)
$width = $this->width;
else
$width = intval($width);
if(!$this->previewDir)
return false;
$document = $documentcontent->getDocument();
$dir = $this->previewDir.'/'.$document->getDir();
$target = $dir.'p'.$documentcontent->getVersion().'-'.$width.'.png';
if(file_exists($target)) {
return true;
}
return false;
} /* }}} */
function getPreview($documentcontent, $width=0) { /* {{{ */
if($width == 0)
$width = $this->width;
else
$width = intval($width);
if(!$this->previewDir)
return false;
$document = $documentcontent->getDocument();
$dir = $this->previewDir.'/'.$document->getDir();
$target = $dir.'p'.$documentcontent->getVersion().'-'.$width.'.png';
if(file_exists($target)) {
readfile($target);
}
} /* }}} */
function deletePreview($document, $documentcontent) { /* {{{ */
if($width == 0)
$width = $this->width;
else
$width = intval($width);
if(!$this->previewDir)
return false;
$dir = $this->previewDir.'/'.$document->getDir();
$target = $dir.'p'.$documentcontent->getVersion().'-'.$width.'.png';
} /* }}} */
}
?>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.8.1" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
<name>SeedDMS_Preview</name>
<channel>pear.php.net</channel>
<summary>Create thumbnails from document content for SeedDMS</summary>
<description>SeedDMS is a web based document management system (DMS). These
are the classes to create preview images from the document content.</description>
<lead>
<name>Uwe Steinmann</name>
<user>steinm</user>
<email>uwe@steinmann.cx</email>
<active>yes</active>
</lead>
<date>2012-11-20</date>
<time>08:05:38</time>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://opensource.org/licenses/gpl-license">GPL License</license>
<notes>
initial version
</notes>
<contents>
<dir baseinstalldir="SeedDMS" name="/">
<dir name="Preview">
<file name="Previewer.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /Lucene -->
<dir name="tests">
</dir> <!-- /tests -->
<file name="Preview.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>4.3.0</min>
</php>
<pearinstaller>
<min>1.5.4</min>
</pearinstaller>
</required>
</dependencies>
<phprelease />
<changelog>
<release>
</release>
</changelog>
</package>

View File

28
TODO
View File

@ -1,14 +1,22 @@
This list is hopelessly outdated, but some of the issues are Show workflow steps after document has been released (keep workflow tab)
still worth to be implemented!
Show documents in calendar when they where uploaded.
Add attribute type 'date'
Update comment and date of a review/approval, if the same status is set Update comment and date of a review/approval, if the same status is set
again. Currently setting the same status is turned of, because it didn't again. Currently setting the same status is turned of, because it didn't
have any effect, which is quite confusing if the user can do an operation have any effect, which is quite confusing if the user can do an operation
which has not the expected result. which has not the expected result.
Show number of documents that needs care (approval, review, any other action
in a workflog) next to Login/Logout-Menu.
Show message on doc info page if documents expects an action like review, Show message on doc info page if documents expects an action like review,
approval, etc. approval, etc.
Import and export of a workflow as xml.
Find a way to make the workflows adjustable when used for a document. Find a way to make the workflows adjustable when used for a document.
e.g. a workflow shall be used for a number of document but the users of e.g. a workflow shall be used for a number of document but the users of
a transtion has to be altered for each document. This is basically reusing a transtion has to be altered for each document. This is basically reusing
@ -23,13 +31,26 @@ the session data. See op.Login.php and op.Logout.php
Allow to specify fine grained notification (e.g. deleting a document, folder) Allow to specify fine grained notification (e.g. deleting a document, folder)
Have access rights depending on document status. This will allow to
restrict access when a document is in a workflow or has been rejected.
There are still global variable in class SeedetoDMS_Bootstrap_Style
Settings::searchConfigFilePath() and Settings::getConfigDir() use different Settings::searchConfigFilePath() and Settings::getConfigDir() use different
approaches to get the configuration directory. approaches to get the configuration directory.
Show expiration status of documents in document list Show expiration status of documents in document list
Export/Import content as xml (even for subfolders)
Copy folders recursivly
Allow operations like delete, move, approve, etc. on a list of documents Allow operations like delete, move, approve, etc. on a list of documents
Upload of multiple documents without an applet
Do not show documents which are not reviewed or approved or rejected
installation script: installation script:
- user simply unpack the tar.gz in a server folder and access that folder - user simply unpack the tar.gz in a server folder and access that folder
- on startup if there are installation problems php automatically run the configuration script - on startup if there are installation problems php automatically run the configuration script
@ -49,6 +70,9 @@ Sometimes in the DB are written messages strings in plain language whose
language depends on the current user and will never be translated. language depends on the current user and will never be translated.
This can be avoided using only coded messages This can be avoided using only coded messages
The mail language is translated using the current user language but should use
the receiver language (not easy).
In my Documents->all documents there should be two lists: one (the current) with In my Documents->all documents there should be two lists: one (the current) with
the user's document, and another with the user's updated document (that's because the user's document, and another with the user's updated document (that's because
one user could have updated a document not owned by himself) one user could have updated a document not owned by himself)

216
build.xml
View File

@ -1,216 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="seeddms" basedir="." default="main">
<property name="tmp" value="/tmp" />
<property name="package" value="${phing.project.name}" override="true" />
<property name="seeddmsurl" value="http://localhost/seeddms51x" />
<property name="builddir" value="${tmp}/build/${phing.project.name}" override="true" />
<property name="srcdir" value="${project.basedir}" override="true" />
<property name="datadir" value="" override="true" />
<property name="dbtype" value="sqlite" override="true" />
<property name="dbhost" value="" override="true" />
<property name="dbuser" value="" override="true" />
<property name="dbpass" value="" override="true" />
<property name="dbname" value="" override="true" />
<property name="version" value="-" />
<property name="shortversion" value="${version}" />
<propertyregex property="shortversion" subject="${version} kk" pattern="([56])\.([0-9]).*" replace="seeddms$1$2x" override="true"/>
<property name="majorversion" value="${version}" />
<propertyregex property="majorversion" subject="${version}" pattern="([56])\..*" replace="$1" override="true"/>
<property name="composer_version" value="2.8.5" />
<property name="composer_extra_params" value="" />
<property name="composer_env" value="" />
<property name="mink_driver" value="chrome" />
<property name="snooze_multiplier" value="1" />
<fileset id="distfiles" dir=".">
<include name="languages/**" />
<include name="op/**" />
<include name="out/**" />
<include name="inc/**" />
<include name="controllers/**" />
<include name="styles/**" />
<include name="views/bootstrap*/**" />
<include name="utils/**" />
<include name="doc/**" />
<include name="webdav/**" />
<include name="install/**" />
<include name="restapi/**" />
<include name="pdfviewer/**" />
<include name="index.php" />
<include name="CHANGELOG" />
<include name=".htaccess" />
<include name="LICENSE" />
</fileset>
<target name="main">
<echo>Hello</echo>
</target>
<!-- PHP CodeSniffer -->
<target name="phpcbf">
<exec command="${srcdir}/vendor/bin/phpcbf --standard=${srcdir}/phpcs.xml" escape="false" passthru="true" checkreturn="true" />
</target>
<target name="phpcs">
<exec command="${srcdir}/vendor/bin/phpcs --standard=${srcdir}/phpcs.xml --report=checkstyle &gt; ${builddir}/reports/checkstyle.xml" escape="false" />
</target>
<target name="phpcs-console">
<exec command="${srcdir}/vendor/bin/phpcs --standard=${srcdir}/phpcs.xml" escape="false" passthru="true" checkreturn="true" />
</target>
<target name="php-cs-fixer-dryrun">
<exec command="${srcdir}/vendor/bin/php-cs-fixer fix --dry-run -vvv --diff ${srcdir}/inc" passthru="true" escape="false" checkreturn="true" />
</target>
<!-- PHPUnit -->
<target name="phpunitfast" description="Run tests">
<exec dir="${srcdir}/SeedDMS_Core" command="XDEBUG_MODE=coverage SEEDDMS_CORE_SQL=../install/create_tables-sqlite3.sql ${srcdir}/vendor/bin/phpunit --bootstrap ${srcdir}/SeedDMS_Core/bootstrap-${majorversion}.php --coverage-html ${srcdir}/coverage/" passthru="true" checkreturn="true" />
<!-- exec dir="${srcdir}/tests" command="SEEDDMS_URL=${seeddmsurl} SEEDDMS_MINK_DRIVER=${mink_driver} SEEDDMS_SNOOZE_MULTIPLIER=${snooze_multiplier} ${srcdir}/vendor/bin/phpunit" passthru="true" checkreturn="true" / -->
</target>
<target name="composer" description="Install dependencies with Composer">
<if>
<equals arg1="${composer_version}" arg2="latest-2.x" />
<then>
<httpget url="https://getcomposer.org/composer-2.phar" sslVerifyPeer="false" dir="${srcdir}" filename="composer.phar" />
</then>
<else>
<if>
<not><available file="composer.phar" /></not>
<then>
<httpget url="https://getcomposer.org/download/${composer_version}/composer.phar" sslVerifyPeer="false" dir="${srcdir}" />
</then>
</if>
</else>
</if>
<echo message="Installing dependencies..." />
<exec command="${composer_env} php ${srcdir}/composer.phar install ${composer_extra_params}" passthru="true" checkreturn="true" />
</target>
<target name="dist" description="build SeedDMS tar archive">
<if>
<equals arg1="-" arg2="${version}" />
<then><fail msg="Pass version as property 'version'" /></then>
</if>
<echo msg="This is ${shortversion}" />
<delete file="./seeddms-${version}.tar.gz" failonerror="false" />
<tar destfile="./seeddms-${version}.tar.gz" prefix="seeddms-${version}" compression="gzip">
<fileset refid="distfiles" />
</tar>
</target>
<target name="package" description="build SeedDMS quickstart packages for distribution">
<if>
<equals arg1="-" arg2="${version}" />
<then><fail msg="Pass version as property 'version'" /></then>
</if>
<echo msg="This is ${shortversion}" />
<if>
<matches string="${version}" pattern="^6\.0\..*" />
<then><echo msg="This is version 6" /></then>
<else><echo msg="This is version 5" /></else>
</if>
<!-- make sure the work area is empty, then rebuild it -->
<delete dir="${builddir}/packages" includeemptydirs="true" failonerror="false" />
<mkdir dir="${builddir}/packages" />
<delete dir="${builddir}/export" includeemptydirs="true" failonerror="false" />
<mkdir dir="${builddir}/export/${shortversion}" />
<mkdir dir="${builddir}/export/${shortversion}/conf" />
<mkdir dir="${builddir}/export/${shortversion}/data" />
<mkdir dir="${builddir}/export/${shortversion}/data/1048576" />
<mkdir dir="${builddir}/export/${shortversion}/data/log" />
<mkdir dir="${builddir}/export/${shortversion}/data/cache" />
<exec command="echo 'Signature: 8a477f597d28d172789f06886806bc55' &gt; ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
<exec command="echo '# This file is a cache directory tag created by seeddms.' &gt;&gt; ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
<exec command="echo '# For information about cache directory tags, see: http://www.brynosaurus.com/cachedir/' &gt;&gt; ${builddir}/export/${shortversion}/data/cache/CACHEDIR.TAG" />
<mkdir dir="${builddir}/export/${shortversion}/data/backup" />
<mkdir dir="${builddir}/export/${shortversion}/data/lucene" />
<mkdir dir="${builddir}/export/${shortversion}/data/staging" />
<mkdir dir="${builddir}/export/${shortversion}/pear" />
<mkdir dir="${builddir}/export/${shortversion}/www" />
<mkdir dir="${builddir}/export/${shortversion}/www/ext" />
<mkdir dir="${builddir}/export/${shortversion}/seeddms-${version}" />
<copy file="${srcdir}/conf/settings.xml.template" tofile="${builddir}/export/${shortversion}/conf/settings.xml">
<filterchain>
<replaceregexp>
<regexp pattern="_DBC_DBTYPE_" replace="${dbtype}"/>
<regexp pattern="_DBC_DBSERVER_" replace="${dbhost}"/>
<regexp pattern="_DBC_DBNAME_" replace="${dbname}"/>
<regexp pattern="_DBC_DBUSER_" replace="${dbuser}"/>
<regexp pattern="_DBC_DBPASS_" replace="${dbpass}"/>
<regexp pattern="_SHORT_VERSION_" replace="${shortversion}"/>
</replaceregexp>
</filterchain>
</copy>
<copy file="${srcdir}/conf/.htaccess" tofile="${builddir}/export/${shortversion}/conf/.htaccess" />
<copy todir="${builddir}/export/${shortversion}/seeddms-${version}">
<fileset refid="distfiles" />
</copy>
<copy todir="${builddir}/export/${shortversion}/pear/vendor">
<fileset dir="${srcdir}/vendor" defaultexcludes="false" />
</copy>
<copy todir="${builddir}/export/${shortversion}/www/ext/example">
<fileset dir="${srcdir}/ext/example" defaultexcludes="false" />
</copy>
<!-- copy todir="${builddir}/export/${shortversion}/pear/SeedDMS">
<fileset dir="SeedDMS_Core">
<include name="Core/**" />
<include name="Core.php" />
</fileset>
<fileset dir="SeedDMS_Preview">
<include name="Preview/**" />
<include name="Preview.php" />
</fileset>
<fileset dir="SeedDMS_Lucene">
<include name="Lucene/**" />
<include name="Lucene.php" />
</fileset -->
<!-- fileset dir="SeedDMS_SQLiteFTS">
<include name="SQLiteFTS/**" />
<include name="SQLiteFTS.php" />
</fileset>
</copy -->
<!-- copy todir="${builddir}/export/${shortversion}/pear">
<fileset dir="../seeddms-ext/http_webdav_server">
<include name="HTTP/WebDAV/Server/**" />
<include name="HTTP/WebDAV/Server.php" />
</fileset>
</copy>
<copy todir="${builddir}/export/${shortversion}/pear/HTTP/WebDAV">
<fileset dir="../seeddms-ext/http_webdav_server">
<include name="Tools/**" />
</fileset>
</copy -->
<copy tofile="${builddir}/export/${shortversion}/pear/composer.json" file="composer-dist.json">
</copy>
<phingcall target="composer">
<property name="composer_extra_params" value="--working-dir=${builddir}/export/${shortversion}/pear/" />
<property name="composer_envv" value="COMPOSER=${srcdir}/composer-dist.json" />
</phingcall>
<exec command="cd ${builddir}/export/${shortversion} &amp;&amp; ln -s seeddms-${version} seeddms" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/op" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/out" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/inc" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/controllers" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/languages" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/views" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/restapi" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/styles" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/pdfviewer" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/install" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/webdav" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/index.php" />
<exec command="cd ${builddir}/export/${shortversion}/www &amp;&amp; ln -s ../seeddms/.htaccess" />
<exec command="cat ${srcdir}/install/create_tables-sqlite3.sql | sqlite3 ${builddir}/export/${shortversion}/data/content.db" />
<!-- build the standard tar.gz archive -->
<echo message="Building .tar.gz...." />
<exec command="cd ${builddir}/export ; tar czf ${builddir}/packages/seeddms-quickstart-${version}.tar.gz ${shortversion}" checkreturn="true" />
<echo message="Built in ${builddir}/packages/seeddms-quickstart-${version}.tar.gz" />
</target>
</project>

View File

@ -1,76 +0,0 @@
{
"config": {
"platform": {
"php": "8.2"
}
},
"require": {
"robthree/twofactorauth": "^1.5",
"slim/slim": "^4.0",
"guzzlehttp/psr7": "*",
"erusev/parsedown": "*",
"erusev/parsedown-extra": "*",
"mibe/feedwriter": "^1.1",
"phpoffice/phpspreadsheet": "*",
"sabre/xml": "*",
"sabre/dav": "^4.",
"pear/log": "*",
"pear/mail": "*",
"pear/mail_mime": "*",
"pear/net_smtp": "*",
"pear/auth_sasl": "*",
"pear/db": "*",
"dragonmantank/cron-expression": "^3.1",
"alecrabbit/php-console-colour": "*",
"dragonmantank/cron-expression": "^3",
"zf1/zend-search-lucene": "*",
"symfony/http-foundation": "^5.4",
"php-di/php-di": "^6.4",
"slim/psr7": "^1.7",
"seeddms/core": "dev-master",
"seeddms/lucene": "dev-master",
"seeddms/preview": "dev-master",
"seeddms/sqlitefts": "dev-master",
"seeddms/http_webdav_server": "dev-master"
},
"require-dev": {
"composer/composer": "dev-main"
},
"repositories": [
{
"type": "path",
"url": "/home/cvs/seeddms-ext/core",
"options": {
"symlink": false
}
},
{
"type": "path",
"url": "/home/cvs/seeddms-ext/lucene",
"options": {
"symlink": false
}
},
{
"type": "path",
"url": "/home/cvs/seeddms-ext/preview",
"options": {
"symlink": false
}
},
{
"type": "path",
"url": "/home/cvs/seeddms-ext/sqlitefts",
"options": {
"symlink": false
}
},
{
"type": "path",
"url": "/home/cvs/seeddms-ext/http_webdav_server",
"options": {
"symlink": false
}
}
]
}

View File

@ -1,10 +1,6 @@
# Make sure settings.xml can not be opened from outside! # Make sure settings.xml can not be opened from outside!
# Deny all requests from Apache 2.4+. #Redirect /conf/settings.xml /index.php
<IfModule mod_authz_core.c> <Files ~ "^settings\.xml">
Require all denied Order allow,deny
</IfModule> Deny from all
</Files>
# Deny all requests from Apache 2.0-2.2.
<IfModule !mod_authz_core.c>
Deny from all
</IfModule>

View File

@ -1,73 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<site> <site>
<!-- <!-- siteName: Name of site used in the page titles. Default: SeedDMS
- siteName: Name of site used in the page titles. Default: SeedDMS
- footNote: Message to display at the bottom of every page - footNote: Message to display at the bottom of every page
- printDisclaimer: if true the disclaimer message the lang.inc files will be print on the bottom of the page - printDisclaimer: if true the disclaimer message the lang.inc files will be print on the bottom of the page
- language: default language (name of a subfolder in folder "languages") - language: default language (name of a subfolder in folder "languages")
- theme: default style (name of a subfolder in folder "styles") - theme: default style (name of a subfolder in folder "styles")
- previewWidthList: Preview image width in folder list
- previewWidthDetail: Preview image width in document view
--> -->
<display <display
siteName = "SeedDMS" siteName = "SeedDMS"
footNote = "SeedDMS free document management system - www.seeddms.org" footNote = "SeedDMS free document management system - www.seeddms.org"
printDisclaimer = "true" printDisclaimer="true"
language = "en_GB" language = "English"
theme = "bootstrap4" theme = "clean"
previewWidthList = "40" >
previewWidthDetail = "100" </display>
onePageMode="true" <!-- strictFormCheck: Strict form checking. If set to true, then all fields in the form will be checked for a value. If set to false, then (most) comments and keyword fields become optional. Comments are always required when submitting a review or overriding document status.
/>
<!--
- strictFormCheck: Strict form checking. If set to true, then all fields in the form will be checked for a value. If set to false, then (most) comments and keyword fields become optional. Comments are always required when submitting a review or overriding document status.
- viewOnlineFileTypes: files with one of the following endings can be viewed online (USE ONLY LOWER CASE CHARACTERS) - viewOnlineFileTypes: files with one of the following endings can be viewed online (USE ONLY LOWER CASE CHARACTERS)
- enableConverting: enable/disable converting of files (deprecated) - enableConverting: enable/disable converting of files
- enableEmail: enable/disable automatic email notification - enableEmail: enable/disable automatic email notification
- enableUsersView: enable/disable group and user view for all users - enableUsersView: enable/disable group and user view for all users
- enableFullSearch: false to don't use fulltext search - enableFullSearch: false to don't use fulltext search
- enableLanguageSelector: false to don't show the language selector after login - enableLanguageSelector: false to don't show the language selector after login
- enableClipboard: false to hide the clipboard
- enableFolderTree: false to don't show the folder tree - enableFolderTree: false to don't show the folder tree
- expandFolderTree: 0 to start with tree hidden - expandFolderTree: 0 to start with tree hidden
- 1 to start with tree shown and first level expanded - 1 to start with tree shown and first level expanded
- 2 to start with tree shown fully expanded - 2 to start with tree shown fully expanded
- stopWordsFile: path to stop word file for indexer - stopWordsFile: path to stop word file for indexer
- sortUsersInList: how to sort users in lists ('fullname' or '' (default)) - sortUsersInList: how to sort users in lists ('fullname' or '' (default))
- enableDropUpload: enable/disable uploading files by drag&drop
- enableRecursiveCount: enable/disable counting docs and folder recursively
- maxRecursiveCount: after this number of docs/folders precise counting will stop
- enableThemeSelector: enable/disable the theme selector on the login page
- fullSearchEngine: Either "lucene" or "sqlitefts"
- sortFoldersDefault: how to sort forders by default. u=unsorted, s=sequence, n=name
- defaultDocPosition: Default position for a new document. 'start', 'end', or ''
- defaultFolderPosition: Default position for a new folder. 'start', 'end', or ''
--> -->
<edition <edition
strictFormCheck = "false" strictFormCheck = "false"
viewOnlineFileTypes = ".txt;.text;.html;.htm;.xml;.pdf;.gif;.png;.jpg;.jpeg;.mp4" viewOnlineFileTypes = ".txt;.text;.html;.htm;.pdf;.gif;.png;.jpg;.jpeg"
enableConverting = "true" enableConverting = "true"
enableEmail = "true" enableEmail = "true"
enableUsersView = "true" enableUsersView = "true"
enableFullSearch = "false" enableFullSearch = "false"
enableClipboard = "false"
enableFolderTree = "true" enableFolderTree = "true"
expandFolderTree = "1" expandFolderTree = "1"
enableLanguageSelector = "true" enableLanguageSelector = "true"
stopWordsFile = "" stopWordsFile = ""
sortUsersInList = "" sortUsersInList = ""
enableDropUpload = "true" >
enableRecursiveCount = "false" </edition>
maxRecursiveCount = "0" <!-- enableCalendar: enable/disable calendar
enableThemeSelector = "true"
fullSearchEngine = "sqlitefts"
sortFoldersDefault = "u"
defaultDocPosition = "end"
defaultFolderPosition = "end"
/>
<!--
- enableCalendar: enable/disable calendar
- calendarDefaultView: calendar default view ("w" for week,"m" for month,"y" for year) - calendarDefaultView: calendar default view ("w" for week,"m" for month,"y" for year)
- firstDayOfWeek: first day of the week (0=sunday, 6=saturday) - firstDayOfWeek: first day of the week (0=sunday, 6=saturday)
--> -->
@ -75,14 +51,12 @@
enableCalendar = "true" enableCalendar = "true"
calendarDefaultView = "y" calendarDefaultView = "y"
firstDayOfWeek = "0" firstDayOfWeek = "0"
/> >
<webdav </calendar>
enableWebdavReplaceDoc="true"
/>
</site> </site>
<system> <system>
<!-- <!-- rootDir: Path to where SeedDMS is located
- rootDir: Path to where SeedDMS is located
- httpRoot: The relative path in the URL, after the domain part. Do not include the - httpRoot: The relative path in the URL, after the domain part. Do not include the
- http:// prefix or the web host name. e.g. If the full URL is - http:// prefix or the web host name. e.g. If the full URL is
- http://www.example.com/seeddms/, set $_httpRoot = "/seeddms/". - http://www.example.com/seeddms/, set $_httpRoot = "/seeddms/".
@ -94,44 +68,31 @@
- logFileEnable: set false to disable log system - logFileEnable: set false to disable log system
- logFileRotation: the log file rotation (h=hourly, d=daily, m=monthly) - logFileRotation: the log file rotation (h=hourly, d=daily, m=monthly)
- enableLargeFileUpload: support for jumploader - enableLargeFileUpload: support for jumploader
- partitionSize: size of chunk uploaded by jumploader - partitionsize: size of chunk uploaded by jumploader
- dropFolderDir: where files for document upload are located - dropFolderDir: where files for document upload are located
- cacheDir: where the preview images are saved - cacheDir: where the preview images are saved
- backupDir: where the backups are saved
--> -->
<server <server
rootDir = "" rootDir = ""
httpRoot = "/_SHORT_VERSION_/" httpRoot = "/seeddms/"
contentDir = "" contentDir = ""
stagingDir = "" stagingDir = ""
luceneDir = "" luceneDir = ""
logFileEnable = "true" logFileEnable = "true"
logFileRotation = "d" logFileRotation = "d"
enableLargeFileUpload = "false" enableLargeFileUpload = "true"
partitionSize = "2000000" partitionSize = "2000000"
dropFolderDir = "" dropFolderDir = ""
cacheDir = "" cacheDir = ""
backupDir = "" >
logFileMaxLevel="6" </server>
/>
<!-- <!-- enableGuestLogin: If you want anybody to login as guest, set the following line to true
- enableGuestLogin: If you want anybody to login as guest, set the following line to true
- note: guest login should be used only in a trusted environment - note: guest login should be used only in a trusted environment
- enablePasswordForgotten: Allow users to reset their password - enablePasswordForgotten: Allow users to reset their password
- restricted: Restricted access: only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP). - restricted: Restricted access: only allow users to log in if they have an entry in the local database (irrespective of successful authentication with LDAP).
- enableUserImage: enable users images - enableUserImage: enable users images
- disableSelfEdit: if true user cannot edit his own profile - disableSelfEdit: if true user cannot edit his own profile
- disableChangePassword: if true user cannot change the password
- passwordStrength: minimum strength of password, set to 0 to disable
- passwordStrengthAlgorithm: algorithm used to calculate password strenght (simple or advanced)
- passwordExpiration: number of days after password expires
- passwordHistory: number of remembered passwords
- loginFailure: maximum allowed login failures before an account is disabled
- autoLoginUser: id of user used if auto login is turned on
- quota: maximum allowed space on disc for each user
- undelUserIds: ids of users which cannot be deleted
- encryptionKey: arbitrary string used for creating form tokens
- cookieLifetime: lifetime of cookie in seconds, set to 0 for session cookies
--> -->
<authentication <authentication
enableGuestLogin = "false" enableGuestLogin = "false"
@ -139,17 +100,7 @@
restricted = "true" restricted = "true"
enableUserImage = "false" enableUserImage = "false"
disableSelfEdit = "false" disableSelfEdit = "false"
disableChangePassword = "false" >
passwordStrength = "0"
passwordStrengthAlgorithm = "simple"
passwordExpiration = "0"
passwordHistory = "0"
loginFailure = "0"
autoLoginUser = "0"
quota = "0"
undelUserIds = ""
encryptionKey = "b8c75fa53c0c7a18a84adb6ca815bd94"
cookieLifetime = "0">
<connectors> <connectors>
<!-- ***** CONNECTOR LDAP ***** <!-- ***** CONNECTOR LDAP *****
- enable: enable/disable connector - enable: enable/disable connector
@ -158,9 +109,6 @@
- URIs are supported, e.g.: ldaps://ldap.host.com - URIs are supported, e.g.: ldaps://ldap.host.com
- port: port of the authentification server - port: port of the authentification server
- baseDN: top level of the LDAP directory tree - baseDN: top level of the LDAP directory tree
- bindDN: use this dn for a first step bind, leave empty for annonymous bind
- bindPw: use this password for a first step bind
- filter: Additional filters which are to be checked
--> -->
<connector <connector
enable = "false" enable = "false"
@ -168,20 +116,14 @@
host = "ldaps://ldap.host.com" host = "ldaps://ldap.host.com"
port = "389" port = "389"
baseDN = "" baseDN = ""
bindDN = "" >
bindPw = "" </connector>
filter = ""
groupField = ""
/>
<!-- ***** CONNECTOR Microsoft Active Directory ***** <!-- ***** CONNECTOR Microsoft Active Directory *****
- enable: enable/disable connector - enable: enable/disable connector
- type: type of connector ldap / AD - type: type of connector ldap / AD
- host: hostname of the authentification server - host: hostname of the authentification server
- port: port of the authentification server - port: port of the authentification server
- baseDN: top level of the LDAP directory tree - baseDN: top level of the LDAP directory tree
- bindDN: use this dn for a first step bind, leave empty for annonymous bind
- bindPw: use this password for a first step bind
- filter: Additional filters which are to be checked
- accountDomainName: sample: example.com - accountDomainName: sample: example.com
--> -->
<connector <connector
@ -191,102 +133,84 @@
port = "389" port = "389"
baseDN = "" baseDN = ""
accountDomainName = "example.com" accountDomainName = "example.com"
bindDN = "" >
bindPw = "" </connector>
filter = ""
groupField = ""
/>
</connectors> </connectors>
</authentication> </authentication>
<!-- <!-- ADOdbPath: Path to adodb. This is the directory containing the adodb directory
- dbDriver: DB-Driver used by adodb (see adodb-readme) - dbDriver: DB-Driver used by adodb (see adodb-readme)
- dbHostname: DB-Server - dbHostname: DB-Server
- dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme) - dbDatabase: database where the tables for seeddms are stored (optional - see adodb-readme)
- dbUser: username for database-access - dbUser: username for database-access
- dbPass: password for database-access - dbPass: password for database-access
- doNotCheckVersion: Whether or not to check the database schema for its correct version.
--> -->
<database <database
ADOdbPath = ""
dbDriver = "_DBC_DBTYPE_" dbDriver = "_DBC_DBTYPE_"
dbHostname = "_DBC_DBSERVER_" dbHostname = "_DBC_DBSERVER_"
dbDatabase = "_DBC_DBNAME_" dbDatabase = "_DBC_DBNAME_"
dbUser = "_DBC_DBUSER_" dbUser = "_DBC_DBUSER_"
dbPass = "_DBC_DBPASS_" dbPass = "_DBC_DBPASS_"
doNotCheckVersion = "false" >
/> </database>
<!-- <!-- smtpServer: SMTP Server hostname
- smtpServer: SMTP Server hostname
- smtpPort: SMTP Server port - smtpPort: SMTP Server port
- smtpSendFrom: Send from - smtpSendFrom: Send from
- smtpUser: user name used for authenticating against smtp server
- smtpPassword: password used for authenticating against smtp server
--> -->
<smtp <smtp
smtpServer = "localhost" smtpServer = "localhost"
smtpPort = "25" smtpPort = "25"
smtpSendFrom = "seeddms@localhost" smtpSendFrom = "seeddms@localhost"
smtpUser = ""
smtpPassword = ""
/> />
</system> </system>
<advanced> <advanced>
<!-- <!-- siteDefaultPage: Default page on login. Defaults to out/out.ViewFolder.php
-siteDefaultPage: Default page on login. Defaults to out/out.ViewFolder.php
- rootFolderID: ID of root-folder (mostly no need to change) - rootFolderID: ID of root-folder (mostly no need to change)
- showMissingTranslations: set true if missing translation shall be listed at end of page - titleDisplayHack: Workaround for page titles that go over more than 2 lines.
--> -->
<display <display
siteDefaultPage = "" siteDefaultPage =""
rootFolderID = "1" rootFolderID = "1"
showMissingTranslations = "false" titleDisplayHack = "true"
/>
<!-- >
- guestID: ID of guest-user used when logged in as guest (mostly no need to change) </display>
<!-- guestID: ID of guest-user used when logged in as guest (mostly no need to change)
- adminIP: if enabled admin can login only by specified IP addres, leave empty to avoid the control - adminIP: if enabled admin can login only by specified IP addres, leave empty to avoid the control
- NOTE: works only with local autentication (no LDAP) - NOTE: works only with local autentication (no LDAP)
--> -->
<authentication <authentication
guestID = "2" guestID = "2"
adminIP = "" adminIP = ""
/> >
</authentication>
<!-- enableAdminRevApp: false to don't list administrator as reviewer/approver <!-- enableAdminRevApp: false to don't list administrator as reviewer/approver
- versioningFileName: the name of the versioning info file created by the backup tool - versioningFileName: the name of the versioning info file created by the backup tool
- workflowMode: 'traditional' or 'advanced' - workflowMode: 'traditional' or 'advanced'
- enableVersionDeletion: allow to delete versions after approval - enableVersionDeletion: allow to delete versions after approval
- enableVersionModification: allow to modify versions after approval - enableVersionModification: allow to modify versions after approval
- enableDuplicateDocNames: allow duplicate names in a folder - enableDuplicateDocNames: allow duplicate names in a folder
- enableDuplicateSubFolderNames: allow duplicate names in a folder
- enableOwnerRevApp: allow owner of a document to review and approve
- enableSelfRevApp: allow the user current logged in to add herself as a reviewer or approver
- presetExpirationDate: set to time period if each document shall expire
- overrideMimeType: set to true if the mimetype of a document version is determined by the server
--> -->
<edition <edition
enableAdminRevApp = "false" enableAdminRevApp = "false"
versioningFileName = "versioning_info.txt" versioningFileName = "versioning_info.txt"
workflowMode = "traditional" workflowMode = "advanced"
enableVersionDeletion = "true" enableVersionDeletion = "true"
enableVersionModification = "true" enableVersionModification = "true"
enableDuplicateDocNames = "true" enableDuplicateDocNames = "true"
enableDuplicateSubFolderNames = "true" >
enableOwnerRevApp = "false" </edition>
enableSelfRevApp = "false" <!-- coreDir: Path to SeedDMS_Core (optional)
presetExpirationDate = ""
overrideMimeType = "false"
/>
<!--
- coreDir: Path to SeedDMS_Core (optional)
- luceneClassDir: Path to SeedDMS_Lucene (optional) - luceneClassDir: Path to SeedDMS_Lucene (optional)
- contentOffsetDir: To work around limitations in the underlying file system, a new - contentOffsetDir: To work around limitations in the underlying file system, a new
- directory structure has been devised that exists within the content - directory structure has been devised that exists within the content
- directory ($_contentDir). This requires a base directory from which - directory ($_contentDir). This requires a base directory from which
- to begin. Usually leave this to the default setting, 1048576, but can - to begin. Usually leave this to the default setting, 1048576, but can
- be any number or string that does not already exist within $_contentDir. - be any number or string that does not already exist within $_contentDir.
- maxDirID: Maximum number of sub-directories per parent directory. Default: 0. - maxDirID: Maximum number of sub-directories per parent directory. Default: 32700.
- updateNotifyTime: users are notified about document-changes that took place within the last "updateNotifyTime" seconds - updateNotifyTime: users are notified about document-changes that took place within the last "updateNotifyTime" seconds
- extraPath: additional path which is added to php's include path
- maxExecutionTime: maximum script execution time, this cannot be larger than the value set in php.ini
- cmdTimeout: timeout in sec. for external commands
--> -->
<server <server
coreDir = "" coreDir = ""
@ -294,35 +218,9 @@
contentOffsetDir = "1048576" contentOffsetDir = "1048576"
maxDirID = "0" maxDirID = "0"
updateNotifyTime = "86400" updateNotifyTime = "86400"
extraPath = "" >
maxExecutionTime = "30" </server>
cmdTimeout = "10"
/>
<!--
- enableNotificationAppRev: set to true if reviewers and approvers shall be informed about a pending review/approval
- enableOwnerNotification: XXX
- enableNotificationWorkflow: set to true if the users in the workflow shall be informed
-->
<notification
enableNotificationAppRev = "true"
enableOwnerNotification = "false"
enableNotificationWorkflow = "false"
/>
<converters target="fulltext">
<converter mimeType="application/pdf">pdftotext -nopgbrk %s -</converter>
<converter mimeType="application/msword">catdoc %s</converter>
<converter mimeType="text/plain">cat %s</converter>
<converter mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document">docx2txt %s -</converter>
</converters>
<converters target="preview">
<converter mimeType="image/png">convert -resize %wx '%f' '%o'</converter>
<converter mimeType="image/jpg">convert -resize %wx '%f' '%o'</converter>
<converter mimeType="image/gif">convert -resize %wx '%f' '%o'</converter>
</converters>
</advanced> </advanced>
<extensions>
<extension name="example" disable="true">
<parameter name="__disable__">1</parameter>
</extension>
</extensions>
</configuration> </configuration>

View File

@ -1,246 +0,0 @@
<?php
/**
* Implementation of AddDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_AddDocument extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $this->params['folder'];
/* Call preAddDocument early, because it might need to modify some
* of the parameters.
*/
if(false === $this->callHook('preAddDocument')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preAddDocument_failed';
return null;
}
$name = $this->getParam('name');
$comment = $this->getParam('comment');
$documentsource = $this->params['documentsource'];
$expires = $this->getParam('expires');
$keywords = $this->getParam('keywords');
$cats = $this->getParam('categories');
$owner = $this->getParam('owner');
$userfiletmp = $this->getParam('userfiletmp');
$userfilename = $this->getParam('userfilename');
$filetype = $this->getParam('filetype');
$userfiletype = $this->getParam('userfiletype');
$sequence = $this->getParam('sequence');
$reviewers = $this->getParam('reviewers');
$approvers = $this->getParam('approvers');
$recipients = $this->getParam('recipients');
$reqversion = $this->getParam('reqversion');
$version_comment = $this->getParam('versioncomment');
$attributes = $this->getParam('attributes');
foreach($attributes as $attrdefid=>&$attribute) {
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
if($attribute) {
switch($attrdef->getType()) {
case SeedDMS_Core_AttributeDefinition::type_date:
if(is_array($attribute))
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
else
$attribute = date('Y-m-d', makeTsFromDate($attribute));
break;
case SeedDMS_Core_AttributeDefinition::type_folder:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
else
$attribute = $dms->getFolder((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_document:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
else
$attribute = $dms->getDocument((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_user:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
else
$attribute = $dms->getUser((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_group:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
else
$attribute = $dms->getGroup((int) $attribute);
break;
}
if(!$attrdef->validate($attribute, null, true)) {
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
return false;
}
} elseif($attrdef->getMinValues() > 0) {
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
return false;
}
} else {
if($ret === false)
return false;
}
}
}
if($attributes_version = $this->getParam('attributesversion')) {
foreach($attributes_version as $attrdefid=>&$attribute) {
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
if($attribute) {
switch($attrdef->getType()) {
case SeedDMS_Core_AttributeDefinition::type_date:
if(is_array($attribute))
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
else
$attribute = date('Y-m-d', makeTsFromDate($attribute));
break;
case SeedDMS_Core_AttributeDefinition::type_folder:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
else
$attribute = $dms->getFolder((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_document:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
else
$attribute = $dms->getDocument((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_user:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
else
$attribute = $dms->getUser((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_group:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
else
$attribute = $dms->getGroup((int) $attribute);
break;
}
if(!$attrdef->validate($attribute, null, true)) {
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
return false;
}
} elseif($attrdef->getMinValues() > 0) {
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
return false;
}
} else {
if($ret === false)
return false;
}
}
}
}
$workflow = $this->getParam('workflow');
$notificationgroups = $this->getParam('notificationgroups');
$notificationusers = $this->getParam('notificationusers');
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
$defaultaccessdocs = $this->getParam('defaultaccessdocs');
$document = $this->callHook('addDocument');
if($document === null) {
$filesize = SeedDMS_Core_File::fileSize($userfiletmp);
$res = $folder->addDocument($name, $comment, $expires, $owner, $keywords,
$cats, $userfiletmp, utf8_basename($userfilename),
$filetype, $userfiletype, $sequence,
$reviewers, $approvers, $reqversion,
$version_comment, $attributes, $attributes_version, $workflow, $initialdocumentstatus);
if (is_bool($res) && !$res) {
$this->errormsg = "error_occured";
return false;
}
$document = $res[0];
/* Set access as specified in settings. */
if($defaultaccessdocs) {
if($defaultaccessdocs > 0 && $defaultaccessdocs < 4) {
$document->setInheritAccess(0, true);
$document->setDefaultAccess($defaultaccessdocs, true);
}
}
$lc = $document->getLatestContent();
if($recipients) {
if($recipients['i']) {
foreach($recipients['i'] as $uid) {
if($u = $dms->getUser($uid)) {
$res = $lc->addIndRecipient($u, $user);
}
}
}
if($recipients['g']) {
foreach($recipients['g'] as $gid) {
if($g = $dms->getGroup($gid)) {
$res = $lc->addGrpRecipient($g, $user);
}
}
}
}
/* Add a default notification for the owner of the document */
if($settings->_enableOwnerNotification) {
$res = $document->addNotify($owner->getID(), true);
}
/* Check if additional notification shall be added */
foreach($notificationusers as $notuser) {
if($document->getAccessMode($notuser) >= M_READ)
$res = $document->addNotify($notuser->getID(), true);
}
foreach($notificationgroups as $notgroup) {
if($document->getGroupAccessMode($notgroup) >= M_READ)
$res = $document->addNotify($notgroup->getID(), false);
}
} elseif($document === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_addDocument_failed';
return false;
}
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $document) {
$idoc = $fulltextservice->IndexedDocument($document);
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
$index->addDocument($idoc);
$index->commit();
}
}
if(false === $this->callHook('postAddDocument', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postAddDocument_failed';
return false;
}
return $document;
} /* }}} */
}

View File

@ -1,136 +0,0 @@
<?php
/**
* Implementation of AddSubFolder controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_AddSubFolder extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $this->params['folder'];
/* Call preAddSubFolder early, because it might need to modify some
* of the parameters.
*/
if(false === $this->callHook('preAddSubFolder')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preAddSubFolder_failed';
return false;
}
$name = $this->getParam('name');
$comment = $this->getParam('comment');
$sequence = $this->getParam('sequence');
$attributes = $this->getParam('attributes');
foreach($attributes as $attrdefid=>&$attribute) {
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
if($attribute) {
switch($attrdef->getType()) {
case SeedDMS_Core_AttributeDefinition::type_date:
if(is_array($attribute))
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
else
$attribute = date('Y-m-d', makeTsFromDate($attribute));
break;
case SeedDMS_Core_AttributeDefinition::type_folder:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
else
$attribute = $dms->getFolder((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_document:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
else
$attribute = $dms->getDocument((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_user:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
else
$attribute = $dms->getUser((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_group:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
else
$attribute = $dms->getGroup((int) $attribute);
break;
}
if(!$attrdef->validate($attribute, null, true)) {
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
return false;
}
} elseif($attrdef->getMinValues() > 0) {
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
return false;
}
} else {
if($ret === false)
return false;
}
}
}
$notificationgroups = $this->getParam('notificationgroups');
$notificationusers = $this->getParam('notificationusers');
$subFolder = $this->callHook('addSubFolder');
if($subFolder === null) {
$subFolder = $folder->addSubFolder($name, $comment, $user, $sequence, $attributes);
if (!is_object($subFolder)) {
$this->errormsg = "error_occured";
return false;
}
/* Check if additional notification shall be added */
foreach($notificationusers as $notuser) {
if($subFolder->getAccessMode($user) >= M_READ)
$res = $subFolder->addNotify($notuser->getID(), true);
}
foreach($notificationgroups as $notgroup) {
if($subFolder->getGroupAccessMode($notgroup) >= M_READ)
$res = $subFolder->addNotify($notgroup->getID(), false);
}
} elseif($subFolder === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_addFolder_failed';
return false;
}
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $subFolder) {
$idoc = $fulltextservice->IndexedDocument($subFolder);
if(false !== $this->callHook('preIndexFolder', $subFolder, $idoc)) {
$index->addDocument($idoc);
$index->commit();
}
}
if(false === $this->callHook('postAddSubFolder', $subFolder)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postAddSubFoder_failed';
return false;
}
return $subFolder;
} /* }}} */
}

View File

@ -1,115 +0,0 @@
<?php
/**
* Implementation of ApproveDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for approving a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ApproveDocument extends SeedDMS_Controller_Common {
public $oldstatus;
public $newstatus;
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$content = $this->params['content'];
$approvaltype = $this->params['type'];
$approvalstatus = $this->params['status'];
$approvalcomment = $this->params['comment'];
$approvalfile = $this->params['file'];
$approvalgroup = $this->params['group'];
$overallStatus = $content->getStatus();
$this->oldstatus = $overallStatus['status'];
$this->newstatus = $this->oldstatus;
if(!$this->callHook('preApproveDocument', $content)) {
}
$result = $this->callHook('approveDocument', $content);
if($result === null) {
if ($approvaltype == "ind") {
$approvalLogID = $content->setApprovalByInd($user, $user, $approvalstatus, $approvalcomment, $approvalfile);
} elseif ($approvaltype == "grp") {
$approvalLogID = $content->setApprovalByGrp($approvalgroup, $user, $approvalstatus, $approvalcomment, $approvalfile);
} else {
$this->errormsg = "approval_wrong_type";
return false;
}
if($approvalLogID === false || 0 > $approvalLogID) {
$this->errormsg = "approval_update_failed";
return false;
}
}
$result = $this->callHook('approveUpdateDocumentStatus', $content);
if($result === null) {
if($approvalstatus == -1) {
$this->newstatus = S_REJECTED;
if($content->setStatus(S_REJECTED, $approvalcomment, $user)) {
if(isset($GLOBALS['SEEDDMS_HOOKS']['approveDocument'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['approveDocument'] as $hookObj) {
if (method_exists($hookObj, 'postApproveDocument')) {
$hookObj->postApproveDocument(null, $content, S_REJECTED);
}
}
}
}
} else {
$docApprovalStatus = $content->getApprovalStatus();
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
$this->errormsg = "cannot_retrieve_approval_snapshot";
return false;
}
$approvalCT = 0;
$approvalTotal = 0;
foreach ($docApprovalStatus as $drstat) {
if ($drstat["status"] == 1) {
$approvalCT++;
}
if ($drstat["status"] != -2) {
$approvalTotal++;
}
}
// If all approvals have been received and there are no rejections, retrieve a
// count of the approvals required for this document.
if ($approvalCT == $approvalTotal) {
// Change the status to released.
$this->newstatus=S_RELEASED;
if($content->setStatus($this->newstatus, getMLText("automatic_status_update"), $user)) {
if(isset($GLOBALS['SEEDDMS_HOOKS']['approveDocument'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['approveDocument'] as $hookObj) {
if (method_exists($hookObj, 'postApproveDocument')) {
$hookObj->postApproveDocument(null, $content, S_RELEASED);
}
}
}
}
}
}
}
if(!$this->callHook('postApproveDocument', $content)) {
}
return true;
} /* }}} */
}

View File

@ -1,95 +0,0 @@
<?php
/**
* Implementation of Attribute Definition manager controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for attribute definition manager
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_AttributeMgr extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
} /* }}} */
public function addattrdef() { /* {{{ */
$dms = $this->params['dms'];
$name = $this->params['name'];
$type = $this->params['type'];
$objtype = $this->params['objtype'];
$multiple = $this->params['multiple'];
$minvalues = $this->params['minvalues'];
$maxvalues = $this->params['maxvalues'];
$valueset = $this->params['valueset'];
$regex = $this->params['regex'];
return($dms->addAttributeDefinition($name, $objtype, $type, $multiple, $minvalues, $maxvalues, $valueset, $regex));
} /* }}} */
public function removeattrdef() { /* {{{ */
$attrdef = $this->params['attrdef'];
return $attrdef->remove();
} /* }}} */
public function editattrdef() { /* {{{ */
$dms = $this->params['dms'];
$name = $this->params['name'];
$attrdef = $this->params['attrdef'];
$type = $this->params['type'];
$objtype = $this->params['objtype'];
$multiple = $this->params['multiple'];
$minvalues = $this->params['minvalues'];
$maxvalues = $this->params['maxvalues'];
$valueset = $this->params['valueset'];
$regex = $this->params['regex'];
if (!$attrdef->setName($name)) {
return false;
}
if (!$attrdef->setType($type)) {
return false;
}
if (!$attrdef->setObjType($objtype)) {
return false;
}
if (!$attrdef->setMultipleValues($multiple)) {
return false;
}
if (!$attrdef->setMinValues($minvalues)) {
return false;
}
if (!$attrdef->setMaxValues($maxvalues)) {
return false;
}
if (!$attrdef->setValueSet($valueset)) {
return false;
}
if (!$attrdef->setRegex($regex)) {
$this->errormsg = 'attrdef_invalid_regex';
return false;
}
return true;
} /* }}} */
public function removeattrvalue() { /* {{{ */
$attrdef = $this->params['attrdef'];
$attrval = $this->params['attrval'];
//$attrdef->getObjects($attrval);
return $attrdef->removeValue($attrval);
} /* }}} */
}

View File

@ -1,114 +0,0 @@
<?php
/**
* Implementation of CheckInDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2024 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2024 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_CheckInDocument extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$name = $this->getParam('name');
$comment = $this->getParam('comment');
/* Call preCheckInDocument early, because it might need to modify some
* of the parameters.
*/
if(false === $this->callHook('preCheckInDocument', $this->params['document'])) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preCheckInDocument_failed';
return null;
}
$comment = $this->getParam('comment');
$dms = $this->params['dms'];
$user = $this->params['user'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $this->params['folder'];
$userfiletmp = $this->getParam('userfiletmp');
$userfilename = $this->getParam('userfilename');
$filetype = $this->getParam('filetype');
$userfiletype = $this->getParam('userfiletype');
$reviewers = $this->getParam('reviewers');
$approvers = $this->getParam('approvers');
$recipients = $this->getParam('recipients');
$reqversion = $this->getParam('reqversion');
$comment = $this->getParam('comment');
$attributes = $this->getParam('attributes');
$workflow = $this->getParam('workflow');
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
$content = $this->callHook('checkinDocument');
if($content === null) {
if($contentResult=$document->checkIn($comment, $user, $reviewers, $approvers, $version=0, $attributes, $workflow, $initialdocumentstatus)) {
if ($this->hasParam('expires')) {
if($document->setExpires($this->getParam('expires'))) {
} else {
}
}
if(!empty($recipients['i'])) {
foreach($recipients['i'] as $uid) {
if($u = $dms->getUser($uid)) {
$res = $contentResult->getContent()->addIndRecipient($u, $user);
}
}
}
if(!empty($recipients['g'])) {
foreach($recipients['g'] as $gid) {
if($g = $dms->getGroup($gid)) {
$res = $contentResult->getContent()->addGrpRecipient($g, $user);
}
}
}
$content = $contentResult->getContent();
} else {
$this->errormsg = 'error_checkin_document';
$result = false;
}
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_checkinDocument_failed';
return false;
}
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $content) {
$idoc = $fulltextservice->IndexedDocument($document);
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
$lucenesearch = $fulltextservice->Search();
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
$index->delete($hit->id);
}
$index->addDocument($idoc);
$index->commit();
}
}
if(false === $this->callHook('postCheckInDocument', $document, $content)) {
}
return $content;
} /* }}} */
}

View File

@ -1,61 +0,0 @@
<?php
/**
* Implementation of ClearCache controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for clearing the cache
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ClearCache extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$post = $this->params['post'];
$ret = '';
if(!empty($post['previewpng'])) {
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'png'.DIRECTORY_SEPARATOR.'[1-9]*';
system($cmd, $ret);
}
if(!empty($post['previewpdf'])) {
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'pdf'.DIRECTORY_SEPARATOR.'[1-9]*';
system($cmd, $ret);
}
if(!empty($post['previewtxt'])) {
$cmd = 'rm -rf '.addDirSep($settings->_cacheDir).'txt'.DIRECTORY_SEPARATOR.'[1-9]*';
system($cmd, $ret);
}
if(!empty($post['js'])) {
/* system('rm ...') does not work anymore if the number of files is too large */
array_map('unlink', array_filter((array) glob(addDirSep($settings->_cacheDir).'js'.DIRECTORY_SEPARATOR.'*')));
}
if(false === $this->callHook('clear', $post)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_clear_failed';
return false;
}
return true;
}
}

View File

@ -1,108 +0,0 @@
<?php
/**
* Implementation of Cron controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2020 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for the regular cron job
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2020 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_Cron extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$logger = $this->params['logger'];
$mode = $this->params['mode'];
$seltask = $this->params['task'];
$db = $dms->getDb();
$scheduler = new SeedDMS_Scheduler($db);
$tasks = $scheduler->getTasks();
$jsonarr = [];
foreach($tasks as $task) {
if($seltask && $seltask != $task->getExtension()."::".$task->getTask())
continue;
if(isset($GLOBALS['SEEDDMS_SCHEDULER']['tasks'][$task->getExtension()]) && is_object($taskobj = resolveTask($GLOBALS['SEEDDMS_SCHEDULER']['tasks'][$task->getExtension()][$task->getTask()]))) {
$arr = array(
'extension'=>$task->getExtension(),
'name'=>$task->getTask(),
'mode'=>$mode,
'disabled' => (bool) $task->getDisabled(),
'isdue' => $task->isDue(),
);
switch($mode) {
case "run":
case "dryrun":
if(method_exists($taskobj, 'execute')) {
if(!$task->getDisabled() && $task->isDue()) {
if($mode == 'run') {
/* Schedule the next run right away to prevent a second execution
* of the task when the cron job of the scheduler is called before
* the last run was finished. The task itself can still be scheduled
* to fast, but this is up to the admin of seeddms.
*/
$task->updateLastNextRun();
if($taskobj->execute($task)) {
add_log_line("Execution of task ".$task->getExtension()."::".$task->getTask()." successful.");
$arr['success'] = true;
} else {
add_log_line("Execution of task ".$task->getExtension()."::".$task->getTask()." failed, task has been disabled.", PEAR_LOG_ERR);
$arr['success'] = false;
$task->setDisabled(1);
}
} elseif($mode == 'dryrun') {
$arr['success'] = true;
}
}
}
break;
case "check":
$arr['error'] = false;
if(!method_exists($taskobj, 'execute')) {
$arr['error'] = true;
$arr['messages'][] = 'Missing method execute()';
}
if(get_parent_class($taskobj) != 'SeedDMS_SchedulerTaskBase') {
$arr['error'] = true;
$arr['error'][] = "Wrong parent class";
}
break;
case "list":
default:
header("Content-Type: application/json");
$arr['nextrun']=$task->getNextRun();
$arr['frequency']=$task->getFrequency();
$arr['params']=array();
if($params = $task->getParameter()) {
foreach($params as $key=>$value) {
$p = $taskobj->getAdditionalParamByName($key);
$arr['params'][$key] = ($p['type'] == 'password') ? '*******' : $value;
}
}
break;
}
$jsonarr[] = $arr;
}
}
echo json_encode($jsonarr);
return true;
} /* }}} */
}

View File

@ -1,209 +0,0 @@
<?php
/**
* Implementation of DocumentAccess controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2017 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for editing a folder
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2017 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_DocumentAccess extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$action = $this->params['action'];
return null;
}
// Change owner -----------------------------------------------------------
public function setowner() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
if(false === $this->callHook('preSetOwner', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preSetOwner_failed';
return null;
}
$newowner = $this->params['newowner'];
$oldowner = $document->getOwner();
if($document->setOwner($newowner)) {
if(false === $this->callHook('postSetOwner', $document, $oldowner)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postSetOwner_failed';
return null;
}
}
return true;
}
public function notinherit() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
if(false === $this->callHook('preSetNotInherit', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preSetNotInherit_failed';
return null;
}
/* Get default access before access is not longer inherited. This
* will return the default access from the parent folder.
*/
$defAccess = $document->getDefaultAccess();
if(!$document->setInheritAccess(false)) {
return false;
}
if(!$document->setDefaultAccess($defAccess)) {
return false;
}
//copy ACL of parent folder
$mode = $this->params['mode'];
if ($mode == "copy") {
$accessList = $folder->getAccessList();
foreach ($accessList["users"] as $userAccess)
$document->addAccess($userAccess->getMode(), $userAccess->getUserID(), true);
foreach ($accessList["groups"] as $groupAccess)
$document->addAccess($groupAccess->getMode(), $groupAccess->getGroupID(), false);
}
if(false === $this->callHook('postSetNotInherit', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postSetNotInherit_failed';
return null;
}
return true;
}
public function inherit() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
if(false === $this->callHook('preSetInherit', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preSetInherit_failed';
return null;
}
if(!$document->clearAccessList() || !$document->setInheritAccess(true)) {
return false;
}
if(false === $this->callHook('postSetInherit', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postSetInherit_failed';
return null;
}
return true;
}
public function setdefault() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
if(false === $this->callHook('preSetDefault', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preSetDefault_failed';
return null;
}
$mode = $this->params['mode'];
if(!$document->setDefaultAccess($mode)) {
return false;
}
if(false === $this->callHook('postSetDefault', $document)) {
if(empty($this->errormsg))
$this->errormsg = 'hook_postSetDefault_failed';
return null;
}
return true;
}
public function editaccess() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$mode = $this->params['mode'];
$userid = $this->params['userid'];
$groupid = $this->params['groupid'];
if ($userid) {
$document->changeAccess($mode, $userid, true);
}
elseif ($groupid) {
$document->changeAccess($mode, $groupid, false);
}
return true;
}
public function delaccess() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$userid = $this->params['userid'];
$groupid = $this->params['groupid'];
if ($userid) {
$document->removeAccess($userid, true);
}
elseif ($groupid) {
$document->removeAccess($groupid, false);
}
return true;
}
public function addaccess() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$folder = $this->params['folder'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$mode = $this->params['mode'];
$userid = $this->params['userid'];
$groupid = $this->params['groupid'];
if ($userid && $userid != -1) {
$document->addAccess($mode, $userid, true);
}
elseif ($groupid && $groupid != -1) {
$document->addAccess($mode, $groupid, false);
}
return true;
}
}

View File

@ -1,213 +0,0 @@
<?php
/**
* Implementation of Download controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_Download extends SeedDMS_Controller_Common {
public function version() { /* {{{ */
$dms = $this->params['dms'];
$version = $this->params['version'];
$document = $this->params['document'];
if($version < 1) {
$content = $this->callHook('documentLatestContent', $document);
if($content === null)
$content = $document->getLatestContent();
} else {
$content = $this->callHook('documentContent', $document, $version);
if($content === null)
$content = $document->getContentByVersion($version);
}
if (!is_object($content)) {
$this->errormsg = 'invalid_version';
return false;
}
/* set params['content'] for compatiblity with older extensions which
* expect the content in the controller
*/
$this->params['content'] = $content;
if(null === $this->callHook('version')) {
if(file_exists($dms->contentDir . $content->getPath())) {
header("Content-Transfer-Encoding: binary");
$efilename = rawurlencode($content->getOriginalFileName());
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
header("Content-Type: " . $content->getMimeType());
header("Cache-Control: must-revalidate");
header("ETag: ".$content->getChecksum());
sendFile($dms->contentDir . $content->getPath());
}
}
return true;
} /* }}} */
public function file() { /* {{{ */
$dms = $this->params['dms'];
$file = $this->params['file'];
if(null === $this->callHook('file')) {
if(file_exists($dms->contentDir . $file->getPath())) {
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"" . $file->getOriginalFileName() . "\"");
header("Content-Type: " . $file->getMimeType());
header("Cache-Control: must-revalidate");
sendFile($dms->contentDir . $file->getPath());
}
}
return true;
} /* }}} */
public function archive() { /* {{{ */
$dms = $this->params['dms'];
$filename = $this->params['file'];
$basedir = $this->params['basedir'];
if(null === $this->callHook('archive')) {
if(file_exists($basedir . $filename)) {
header('Content-Description: File Transfer');
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
$efilename = rawurlencode($filename);
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
header("Cache-Control: public");
sendFile($basedir .$filename );
}
}
return true;
} /* }}} */
public function log() { /* {{{ */
$dms = $this->params['dms'];
$filename = $this->params['file'];
$basedir = $this->params['basedir'];
if(null === $this->callHook('log')) {
if(file_exists($basedir . $filename)) {
header("Content-Type: text/plain; name=\"" . $filename . "\"");
header("Content-Transfer-Encoding: binary");
$efilename = rawurlencode($filename);
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
header("Cache-Control: must-revalidate");
sendFile($basedir.$filename);
}
}
return true;
} /* }}} */
public function sqldump() { /* {{{ */
$dms = $this->params['dms'];
$filename = $this->params['file'];
$basedir = $this->params['basedir'];
if(null === $this->callHook('sqldump')) {
if(file_exists($basedir . $filename)) {
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
$efilename = rawurlencode($filename);
header("Content-Disposition: attachment; filename=\"" .$efilename . "\"; filename*=UTF-8''".$efilename);
header("Cache-Control: must-revalidate");
sendFile($basedir.$filename);
}
}
return true;
} /* }}} */
public function approval() { /* {{{ */
$dms = $this->params['dms'];
$document = $this->params['document'];
$logid = $this->params['approvelogid'];
$filename = $dms->contentDir . $document->getDir().'a'.$logid;
if (!file_exists($filename) ) {
$this->error = 1;
return false;
}
if(null === $this->callHook('approval')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename);
header("Content-Type: ".$mimetype);
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"approval-" . $document->getID()."-".(int) $_GET['approvelogid'] . get_extension($mimetype) . "\"");
header("Cache-Control: must-revalidate");
sendFile($filename);
}
return true;
} /* }}} */
public function review() { /* {{{ */
$dms = $this->params['dms'];
$document = $this->params['document'];
$logid = $this->params['reviewlogid'];
$filename = $dms->contentDir . $document->getDir().'r'.$logid;
if (!file_exists($filename) ) {
$this->error = 1;
return false;
}
if(null === $this->callHook('review')) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename);
header("Content-Type: ".$mimetype);
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename ));
header("Content-Disposition: attachment; filename=\"review-" . $document->getID()."-".(int) $_GET['reviewlogid'] . get_extension($mimetype) . "\"");
header("Cache-Control: must-revalidate");
sendFile($filename);
}
return true;
} /* }}} */
public function run() { /* {{{ */
$dms = $this->params['dms'];
$type = $this->params['type'];
switch($type) {
case "version":
return $this->version();
break;
case "file":
return $this->file();
break;
case "archive":
return $this->archive();
break;
case "log":
return $this->log();
break;
case "sqldump":
return $this->sqldump();
break;
case "approval":
return $this->approval();
break;
case "review":
return $this->review();
break;
}
} /* }}} */
}

View File

@ -1,220 +0,0 @@
<?php
/**
* Implementation of EditDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for editing a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_EditDocument extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$fulltextservice = $this->params['fulltextservice'];
$document = $this->params['document'];
$name = $this->params['name'];
if(false === $this->callHook('preEditDocument')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preEditDocument_failed';
return null;
}
$result = $this->callHook('editDocument', $document);
if($result === null) {
$name = $this->params['name'];
$oldname = $document->getName();
if($oldname != $name)
if(!$document->setName($name))
return false;
$comment = $this->params['comment'];
if(($oldcomment = $document->getComment()) != $comment)
if(!$document->setComment($comment))
return false;
$expires = $this->params['expires'];
$oldexpires = $document->getExpires();
if ($expires != $oldexpires) {
if(false === $this->callHook('preSetExpires', $document, $expires)) {
}
if(!$document->setExpires($expires)) {
return false;
}
$document->verifyLastestContentExpriry();
if(false === $this->callHook('postSetExpires', $document, $expires)) {
}
}
$keywords = $this->params['keywords'];
$oldkeywords = $document->getKeywords();
if ($oldkeywords != $keywords) {
if(false === $this->callHook('preSetKeywords', $document, $keywords, $oldkeywords)) {
}
if(!$document->setKeywords($keywords)) {
return false;
}
if(false === $this->callHook('postSetKeywords', $document, $keywords, $oldkeywords)) {
}
}
$categories = $this->params['categories'];
$oldcategories = $document->getCategories();
if($categories) {
$categoriesarr = array();
foreach($categories as $catid) {
if($cat = $dms->getDocumentCategory($catid)) {
$categoriesarr[] = $cat;
}
}
$oldcatsids = array();
foreach($oldcategories as $oldcategory)
$oldcatsids[] = $oldcategory->getID();
if (count($categoriesarr) != count($oldcategories) ||
array_diff($categories, $oldcatsids)) {
if(false === $this->callHook('preSetCategories', $document, $categoriesarr, $oldcategories)) {
}
if(!$document->setCategories($categoriesarr)) {
return false;
}
if(false === $this->callHook('postSetCategories', $document, $categoriesarr, $oldcategories)) {
}
}
} elseif($oldcategories) {
if(false === $this->callHook('preSetCategories', $document, array(), $oldcategories)) {
}
if(!$document->setCategories(array())) {
return false;
}
if(false === $this->callHook('postSetCategories', $document, array(), $oldcategories)) {
}
}
$attributes = $this->params['attributes'];
$oldattributes = $document->getAttributes();
if($attributes) {
foreach($attributes as $attrdefid=>$attribute) {
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
if($attribute) {
switch($attrdef->getType()) {
case SeedDMS_Core_AttributeDefinition::type_date:
if(is_array($attribute))
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
else
$attribute = date('Y-m-d', makeTsFromDate($attribute));
break;
case SeedDMS_Core_AttributeDefinition::type_folder:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
else
$attribute = $dms->getFolder((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_document:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
else
$attribute = $dms->getDocument((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_user:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
else
$attribute = $dms->getUser((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_group:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
else
$attribute = $dms->getGroup((int) $attribute);
break;
}
if(!$attrdef->validate($attribute, $document, false)) {
$this->errormsg = getAttributeValidationError($attrdef->getValidationError(), $attrdef->getName(), $attribute);
return false;
}
if(!isset($oldattributes[$attrdefid]) || $attribute != $oldattributes[$attrdefid]->getValue()) {
if(!$document->setAttributeValue($dms->getAttributeDefinition($attrdefid), $attribute))
return false;
}
} elseif($attrdef->getMinValues() > 0) {
$this->errormsg = array("attr_min_values", array("attrname"=>$attrdef->getName()));
} elseif(isset($oldattributes[$attrdefid])) {
if(!$document->removeAttribute($dms->getAttributeDefinition($attrdefid)))
return false;
}
} else {
if($ret === false)
return false;
}
}
}
}
foreach($oldattributes as $attrdefid=>$oldattribute) {
if(!isset($attributes[$attrdefid])) {
if(!$document->removeAttribute($dms->getAttributeDefinition($attrdefid)))
return false;
}
}
$sequence = $this->params['sequence'];
if(strcasecmp($sequence, "keep")) {
if($document->setSequence($sequence)) {
} else {
return false;
}
}
/* There are various hooks in inc/inc.FulltextInit.php which will take
* care of reindexing it. They just delete the indexing date which is
* faster then indexing the folder completely
*
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $document) {
$idoc = $fulltextservice->IndexedDocument($document);
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
$lucenesearch = $fulltextservice->Search();
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
$index->delete($hit->id);
}
$index->addDocument($idoc);
$index->commit();
}
}
*/
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_editDocument_failed';
return false;
}
if(false === $this->callHook('postEditDocument')) {
}
return true;
}
}

View File

@ -1,68 +0,0 @@
<?php
/**
* Implementation of EditDocumentFile controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for editing a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_EditDocumentFile extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$document = $this->params['document'];
$file = $this->params['file'];
if(false === $this->callHook('preEditDocumentFile')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preEditDocumentFile_failed';
return null;
}
$result = $this->callHook('editDocumentFile', $document);
if($result === null) {
$name = $this->params['name'];
$oldname = $file->getName();
if($oldname != $name)
if(!$file->setName($name))
return false;
$comment = $this->params['comment'];
if(($oldcomment = $file->getComment()) != $comment)
if(!$file->setComment($comment))
return false;
$version = $this->params["version"];
$oldversion = $file->getVersion();
if ($oldversion != $version)
if(!$file->setVersion($version))
return false;
$public = $this->params["public"];
$file->setPublic($public == 'true' ? 1 : 0);
if(!$this->callHook('postEditDocumentFile')) {
}
} else
return $result;
return true;
}
}

View File

@ -1,155 +0,0 @@
<?php
/**
* Implementation of EditFolder controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for editing a folder
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_EditFolder extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $this->params['folder'];
if(false === $this->callHook('preEditFolder')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preEditFolder_failed';
return null;
}
$result = $this->callHook('editFolder', $folder);
if($result === null) {
$name = $this->params['name'];
if(($oldname = $folder->getName()) != $name)
if(!$folder->setName($name))
return false;
$comment = $this->params['comment'];
if(($oldcomment = $folder->getComment()) != $comment)
if(!$folder->setComment($comment))
return false;
$attributes = $this->params['attributes'];
$oldattributes = $folder->getAttributes();
if($attributes) {
foreach($attributes as $attrdefid=>$attribute) {
if($attrdef = $dms->getAttributeDefinition($attrdefid)) {
if(null === ($ret = $this->callHook('validateAttribute', $attrdef, $attribute))) {
if($attribute) {
switch($attrdef->getType()) {
case SeedDMS_Core_AttributeDefinition::type_date:
if(is_array($attribute))
$attribute = array_map(fn($value): string => date('Y-m-d', makeTsFromDate($value)), $attribute);
else
$attribute = date('Y-m-d', makeTsFromDate($attribute));
break;
case SeedDMS_Core_AttributeDefinition::type_folder:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getFolder((int) $value), $attribute);
else
$attribute = $dms->getFolder((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_document:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getDocument((int) $value), $attribute);
else
$attribute = $dms->getDocument((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_user:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getUser((int) $value), $attribute);
else
$attribute = $dms->getUser((int) $attribute);
break;
case SeedDMS_Core_AttributeDefinition::type_group:
if(is_array($attribute))
$attribute = array_map(fn($value): object => $dms->getGroup((int) $value), $attribute);
else
$attribute = $dms->getGroup((int) $attribute);
break;
}
if(!$attrdef->validate($attribute, $folder, false)) {
$this->errormsg = getAttributeValidationText($attrdef->getValidationError(), $attrdef->getName(), $attribute);
return false;
}
if(!isset($oldattributes[$attrdefid]) || $attribute != $oldattributes[$attrdefid]->getValue()) {
if(!$folder->setAttributeValue($dms->getAttributeDefinition($attrdefid), $attribute))
return false;
}
} elseif($attrdef->getMinValues() > 0) {
$this->errormsg = getMLText("attr_min_values", array("attrname"=>$attrdef->getName()));
return false;
} elseif(isset($oldattributes[$attrdefid])) {
if(!$folder->removeAttribute($dms->getAttributeDefinition($attrdefid)))
return false;
}
} else {
if($ret === false)
return false;
}
}
}
}
foreach($oldattributes as $attrdefid=>$oldattribute) {
if(!isset($attributes[$attrdefid])) {
if(!$folder->removeAttribute($dms->getAttributeDefinition($attrdefid)))
return false;
}
}
$sequence = $this->params['sequence'];
if(strcasecmp($sequence, "keep")) {
if($folder->setSequence($sequence)) {
} else {
return false;
}
}
/* There are various hooks in inc/inc.FulltextInit.php which will take
* care of reindexing it. They just delete the indexing date which is
* faster then indexing the folder completely
*
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $folder) {
$idoc = $fulltextservice->IndexedDocument($folder);
if(false !== $this->callHook('preIndexFolder', $folder, $idoc)) {
$lucenesearch = $fulltextservice->Search();
if($hit = $lucenesearch->getFolder((int) $folder->getId())) {
$index->delete($hit->id);
}
$index->addDocument($idoc);
$index->commit();
}
}
*/
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_editFolder_failed';
return false;
}
if(false === $this->callHook('postEditFolder')) {
}
return true;
}
}

View File

@ -1,98 +0,0 @@
<?php
/**
* Implementation of EmptyFolder controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_EmptyFolder extends SeedDMS_Controller_Common {
/* Register a callback which removes each document/folder from the fulltext index
* The callback must return null otherwise the removal will be canceled.
*/
static function removeFromIndex($arr, $object) { /* {{{ */
$fulltextservice = $arr[0];
$lucenesearch = $fulltextservice->Search();
$hit = null;
if($object->isType('document'))
$hit = $lucenesearch->getDocument($object->getID());
elseif($object->isType('folder'))
$hit = $lucenesearch->getFolder($object->getID());
if($hit) {
$index = $fulltextservice->Indexer();
$index->delete($hit->id);
$index->commit();
}
return null;
} /* }}} */
static function removePreviews($arr, $document) { /* {{{ */
$previewer = $arr[0];
$previewer->deleteDocumentPreviews($document);
return null;
} /* }}} */
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$folder = $this->params['folder'];
$fulltextservice = $this->params['fulltextservice'];
/* Get the folder id and name before removing the folder */
$foldername = $folder->getName();
$folderid = $folder->getID();
if(false === $this->callHook('preEmptyFolder')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preEmptyFolder_failed';
return false;
}
$result = $this->callHook('emptyFolder', $folder);
if($result === null) {
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
/* Register a callback which is called by SeedDMS_Core when a folder
* or document is removed. The second parameter passed to this callback
* is the document or folder to be removed.
*/
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice));
$dms->addCallback('onPreRemoveFolder', 'SeedDMS_Controller_EmptyFolder::removeFromIndex', array($fulltextservice));
}
/* Register another callback which removes the preview images of the document */
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_EmptyFolder::removePreviews', array($previewer));
if (!$folder->emptyFolder()) {
$this->errormsg = 'error_occured';
return false;
}
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_emptyFolder_failed';
return false;
}
if(false === $this->callHook('postEmptyFolder')) {
}
return true;
} /* }}} */
}

View File

@ -1,97 +0,0 @@
<?php
/**
* Implementation of ExtensionMgr controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2018 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for managing extensions
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2018 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ExtensionMgr extends SeedDMS_Controller_Common {
public function refresh() { /* {{{ */
$dms = $this->params['dms'];
$extmgr = $this->params['extmgr'];
$extmgr->createExtensionConf();
return true;
} /* }}} */
public function download() { /* {{{ */
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$extmgr = $this->params['extmgr'];
$extname = $this->params['extname'];
$filename = $extmgr->createArchive($extname, $extmgr->getExtensionConfiguration()[$extname]['version']);
if(null === $this->callHook('download')) {
if(file_exists($filename)) {
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename=\"" . utf8_basename($filename) . "\"; filename*=UTF-8''".utf8_basename($filename));
header("Content-Type: application/zip");
header("Cache-Control: must-revalidate");
sendFile($filename);
}
}
return true;
} /* }}} */
public function upload() { /* {{{ */
$dms = $this->params['dms'];
$extmgr = $this->params['extmgr'];
$file = $this->params['file'];
if($extmgr->updateExtension($file)) {
$extmgr->createExtensionConf();
} else {
$this->setErrorMsg($extmgr->getErrorMsg());
return false;
}
return true;
} /* }}} */
public function getlist() { /* {{{ */
$dms = $this->params['dms'];
$extmgr = $this->params['extmgr'];
$forceupdate = $this->params['forceupdate'];
$version = $this->params['version'];
if(!$extmgr->updateExtensionList($version, $forceupdate)) {
$this->errormsg = $extmgr->getErrorMsg();
return false;
}
return true;
} /* }}} */
public function toggle() { /* {{{ */
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$extmgr = $this->params['extmgr'];
$extname = $this->params['extname'];
if($settings->extensionIsDisabled($extname))
$settings->enableExtension($extname);
else
$settings->disableExtension($extname);
$settings->save();
return true;
} /* }}} */
}

View File

@ -1,276 +0,0 @@
<?php
/**
* Implementation of Login controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic when logging in
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_Login extends SeedDMS_Controller_Common {
/**
* @var array $user set if user could be logged in
* @access protected
*/
static protected $user;
public function getUser() { /* {{{ */
return self::$user;
} /* }}} */
public function _finalize($user) { /* {{{ */
$settings = $this->params['settings'];
$session = $this->params['session'];
$sesstheme = $this->params['sesstheme'];
$source = isset($this->params['source']) ? $this->params['source'] : '';
$lang = $this->params['lang'];
self::$user = $user;
/* Check for other restrictions which prevent the user from login, though
* the authentication was successfull.
* Checking for a guest login the second time, makes only sense if there are
* more guest users and the login was done with a password and a user name
* unequal to 'guest'.
*/
$userid = $user->getID();
if (($userid == $settings->_guestID) && (!$settings->_enableGuestLogin)) {
$this->setErrorMsg("guest_login_disabled");
return false;
}
// Check if account is disabled
if($user->isDisabled()) {
$this->setErrorMsg("login_disabled_text");
return false;
}
// control admin IP address if required
if ($user->isAdmin() && ($_SERVER['REMOTE_ADDR'] != $settings->_adminIP ) && ( $settings->_adminIP != "") ){
$this->setErrorMsg("invalid_user_id");
return false;
}
if($settings->_enable2FactorAuthentication) {
if($user->getSecret()) {
$tfa = new \RobThree\Auth\TwoFactorAuth('SeedDMS');
if($tfa->verifyCode($user->getSecret(), $_POST['twofactauth']) !== true) {
$this->setErrorMsg("login_error_text");
return false;
}
}
}
/* Run any additional checks which may prevent login */
if(false === $this->callHook('restrictLogin', $user)) {
if(empty($this->errormsg))
$this->setErrorMsg("login_restrictions_apply");
return false;
}
/* Clear login failures if login was successful */
$user->clearLoginFailures();
/* Setting the theme and language and all the cookie handling is
* only done when authentication was requested from a weg page.
*/
if($source == 'web') {
// Capture the user's language and theme settings.
if ($lang) {
$user->setLanguage($lang);
} else {
$lang = $user->getLanguage();
if (strlen($lang)==0) {
$lang = $settings->_language;
$user->setLanguage($lang);
}
}
if ($sesstheme) {
$user->setTheme($sesstheme);
}
else {
$sesstheme = $user->getTheme();
/* Override the theme if the user doesn't have one or the default theme
* shall override it.
*/
if (strlen($sesstheme)==0 || !empty($settings->_overrideTheme)) {
$sesstheme = $settings->_theme;
// $user->setTheme($sesstheme);
}
}
// Delete all sessions that are more than 1 week or the configured
// cookie lifetime old. Probably not the most
// reliable place to put this check -- move to inc.Authentication.php?
if($settings->_cookieLifetime)
$lifetime = intval($settings->_cookieLifetime);
else
$lifetime = 7*86400;
if(!$session->deleteByTime($lifetime)) {
$this->setErrorMsg("error_occured");
return false;
}
if (isset($_COOKIE["mydms_session"])) {
/* This part will never be reached unless the session cookie is kept,
* but op.Logout.php deletes it. Keeping a session could be a good idea
* for retaining the clipboard data, but the user id in the session should
* be set to 0 which is not possible due to foreign key constraints.
* So for now op.Logout.php will delete the cookie as always
*/
/* Load session */
$dms_session = $_COOKIE["mydms_session"];
if(!$resArr = $session->load($dms_session)) {
/* Turn off http only cookies if jumploader is enabled */
setcookie("mydms_session", $dms_session, time()-3600, $settings->_httpRoot, null, false, true); //delete cookie
header("Location: " . $settings->_httpRoot . "out/out.Login.php?referuri=".$referuri);
exit;
} else {
$session->updateAccess($dms_session);
$session->setUser($userid);
}
} else {
// Create new session in database
if(!$id = $session->create(array('userid'=>$userid, 'theme'=>$sesstheme, 'lang'=>$lang))) {
$this->setErrorMsg("error_occured");
return false;
}
// Set the session cookie.
if($settings->_cookieLifetime)
$lifetime = time() + intval($settings->_cookieLifetime);
else
$lifetime = 0;
setcookie("mydms_session", $id, $lifetime, $settings->_httpRoot, null, false, true);
}
}
if($this->callHook('postLogin', $user)) {
}
return true;
} /* }}} */
public function run() { /* {{{ */
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$session = $this->params['session'];
$authenticator = $this->params['authenticator'];
$source = isset($this->params['source']) ? $this->params['source'] : '';
$sesstheme = $this->getParam('sesstheme');
$referuri = $this->getParam('referuri');
$lang = $this->getParam('lang');
$login = $this->params['login'];
$pwd = $this->params['pwd'];
self::$user = null;
/* The preLogin hook may set self::$user which will prevent any further
* authentication process.
*/
if($this->callHook('preLogin')) {
}
$user = self::$user;
/* The password may only be empty if the guest user tries to log in.
* There is just one guest account with id $settings->_guestID which
* is allowed to log in without a password. All other guest accounts
* are treated like regular logins
*/
if(!$user && $settings->_enableGuestLogin && (int) $settings->_guestID) {
$guestUser = $dms->getUser((int) $settings->_guestID);
if($guestUser) {
if(($login != $guestUser->getLogin())) {
if ((!isset($pwd) || strlen($pwd)==0)) {
$this->setErrorMsg("login_error_text");
return false;
}
} else {
$user = $guestUser;
}
}
}
/* Run any additional authentication method. The hook must return a
* valid user, if the authentication succeeded. If it fails, it must
* return false and if the hook doesn't care at all, if must return null.
*/
if(!$user) {
$user = $this->callHook('authenticate', $source);
if(false === $user) {
if(empty($this->errormsg))
$this->setErrorMsg("authentication_failed");
return false;
}
}
/* Deprecated: Run any additional authentication implemented in a hook */
if(!is_object($user) && isset($GLOBALS['SEEDDMS_HOOKS']['authentication'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['authentication'] as $authObj) {
if(!$user && method_exists($authObj, 'authenticate')) {
$user = $authObj->authenticate($dms, $settings, $login, $pwd);
if(false === $user) {
if(empty($this->errormsg))
$this->setErrorMsg("authentication_failed");
return false;
}
}
}
}
if(!is_object($user))
$user = $authenticator->authenticate($login, $pwd);
if(0) {
/* Authenticate against LDAP server {{{ */
if (!is_object($user) && isset($settings->_ldapHost) && strlen($settings->_ldapHost)>0) {
require_once("../inc/inc.ClassLdapAuthentication.php");
$authobj = new SeedDMS_LdapAuthentication($dms, $settings);
$user = $authobj->authenticate($login, $pwd);
if(!$user) {
add_log_line('Authentication against LDAP failed for user '.$login);
}
} /* }}} */
/* Authenticate against SeedDMS database {{{ */
if(!is_object($user)) {
require_once("../inc/inc.ClassDbAuthentication.php");
$authobj = new SeedDMS_DbAuthentication($dms, $settings);
$user = $authobj->authenticate($login, $pwd);
} /* }}} */
}
/* If the user is still not authenticated, then exit with an error */
if(!is_object($user)) {
/* if counting of login failures is turned on, then increment its value */
if($settings->_loginFailure) {
$user = $dms->getUserByLogin($login);
if($user) {
$failures = $user->addLoginFailure();
if($failures >= $settings->_loginFailure)
$user->setDisabled(true);
}
}
$this->callHook('loginFailed');
$this->setErrorMsg("login_error_text");
return false;
}
return self::_finalize($user);
} /* }}} */
}

View File

@ -1,34 +0,0 @@
<?php
/**
* Implementation of Logout controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic when logging in
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_Logout extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$session = $this->params['session'];
if($this->callHook('postLogout')) {
}
}
}

View File

@ -1,78 +0,0 @@
<?php
/**
* Implementation of PdfPreview controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for previewing a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_PdfPreview extends SeedDMS_Controller_Common {
public function run() {
global $theme;
$dms = $this->params['dms'];
$type = $this->params['type'];
$settings = $this->params['settings'];
$conversionmgr = $this->params['conversionmgr'];
switch($type) {
case "version":
$version = $this->params['version'];
$document = $this->params['document'];
if($version < 1) {
$content = $this->callHook('documentLatestContent', $document);
if($content === null)
$content = $document->getLatestContent();
} else {
$content = $this->callHook('documentContent', $document, $version);
if($content === null)
$content = $document->getContentByVersion($version);
}
if (!is_object($content)) {
$this->errormsg = 'invalid_version';
return false;
}
/* set params['content'] for compatiblity with older extensions which
* expect the content in the controller
*/
$this->params['content'] = $content;
if(null === $this->callHook('version')) {
$previewer = new SeedDMS_Preview_PdfPreviewer($settings->_cacheDir, $settings->_cmdTimeout);
if($conversionmgr)
$previewer->setConversionMgr($conversionmgr);
else
$previewer->setConverters(isset($settings->_converters['pdf']) ? $settings->_converters['pdf'] : array());
$previewer->setXsendfile($settings->_enableXsendfile);
if(!$previewer->hasPreview($content)) {
add_log_line("");
if(!$previewer->createPreview($content)) {
add_log_line("", PEAR_LOG_ERR);
}
}
if(!$previewer->hasPreview($content)) {
header('Content-Type: application/pdf');
readfile('../views/'.$theme.'/images/empty.pdf');
exit;
}
header('Content-Type: application/pdf');
$previewer->getPreview($content);
}
break;
}
return true;
}
}

View File

@ -1,114 +0,0 @@
<?php
/**
* Implementation of Preview controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for previewing a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_Preview extends SeedDMS_Controller_Common {
public function version() { /* {{{ */
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$conversionmgr = $this->params['conversionmgr'];
$version = $this->params['version'];
$document = $this->params['document'];
$width = $this->params['width'];
if($version < 1) {
$content = $this->callHook('documentLatestContent', $document);
if($content === null)
$content = $document->getLatestContent();
} else {
$content = $this->callHook('documentContent', $document, $version);
if($content === null)
$content = $document->getContentByVersion($version);
}
if (!is_object($content)) {
$this->errormsg = 'invalid_version';
return false;
}
/* set params['content'] for compatiblity with older extensions which
* expect the content in the controller
*/
$this->params['content'] = $content;
if(null === $this->callHook('version')) {
if($width)
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width, $settings->_cmdTimeout);
else
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
if($conversionmgr)
$previewer->setConversionMgr($conversionmgr);
else
$previewer->setConverters($settings->_converters['preview']);
$previewer->setXsendfile($settings->_enableXsendfile);
if(!$previewer->hasPreview($content)) {
add_log_line("");
if(!$previewer->createPreview($content)) {
add_log_line("", PEAR_LOG_ERR);
}
}
if(!$previewer->hasPreview($content)) {
return false;
}
header('Content-Type: image/png');
$previewer->getPreview($content);
return true;
}
} /* }}} */
public function file() { /* {{{ */
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$conversionmgr = $this->params['conversionmgr'];
$object = $this->params['object'];
$document = $this->params['document'];
$width = $this->params['width'];
if (!is_object($object)) {
$this->errormsg = 'invalid_version';
return false;
}
if(null === $this->callHook('file')) {
if($width)
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir, $width, $settings->_cmdTimeout);
else
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
if($conversionmgr)
$previewer->setConversionMgr($conversionmgr);
else
$previewer->setConverters($settings->_converters['preview']);
$previewer->setXsendfile($settings->_enableXsendfile);
if(!$previewer->hasPreview($object)) {
add_log_line("");
if(!$previewer->createPreview($object)) {
add_log_line("", PEAR_LOG_ERR);
}
}
if(!$previewer->hasPreview($object)) {
return false;
}
header('Content-Type: image/png');
$previewer->getPreview($object);
return true;
}
} /* }}} */
}

View File

@ -1,67 +0,0 @@
<?php
/**
* Implementation of ReceiptDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ReceiptDocument extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$document = $this->params['document'];
$content = $this->params['content'];
$receiptstatus = $this->params['receiptstatus'];
$receipttype = $this->params['receipttype'];
$group = $this->params['group'];
$comment = $this->params['comment'];
/* Get the document id and name before removing the document */
$docname = $document->getName();
$documentid = $document->getID();
if(!$this->callHook('preReceiptDocument', $content)) {
}
$result = $this->callHook('receiptDocument', $content);
if($result === null) {
if ($receipttype == "ind") {
if(0 > $content->setReceiptByInd($user, $user, $receiptstatus, $comment)) {
$this->error = 1;
$this->errormsg = "receipt_update_failed";
return false;
}
} elseif ($receipttype == "grp") {
if(0 > $content->setReceiptByGrp($group, $user, $receiptstatus, $comment)) {
$this->error = 1;
$this->errormsg = "receipt_update_failed";
return false;
}
}
}
if(!$this->callHook('postReceiptDocument', $content)) {
}
return true;
}
}

View File

@ -1,75 +0,0 @@
<?php
/**
* Implementation of RemoveDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_RemoveDocument extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$document = $this->params['document'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $document->getFolder();
/* Get the document id and name before removing the document */
$docname = $document->getName();
$documentid = $document->getID();
if(false === $this->callHook('preRemoveDocument')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preRemoveDocument_failed';
return false;
}
$result = $this->callHook('removeDocument', $document);
if($result === null) {
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
$previewer->deleteDocumentPreviews($document);
if (!$document->remove()) {
if($dms->lasterror)
$this->errormsg = $dms->lasterror;
else
$this->errormsg = "error_occured";
return false;
}
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_removeDocument_failed';
return false;
}
/* Remove the document from the fulltext index */
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
$lucenesearch = $fulltextservice->Search();
if($hit = $lucenesearch->getDocument($documentid)) {
$index->delete($hit->id);
$index->commit();
}
}
if(false === $this->callHook('postRemoveDocument')) {
}
return true;
}
}

View File

@ -1,98 +0,0 @@
<?php
/**
* Implementation of RemoveFolder controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_RemoveFolder extends SeedDMS_Controller_Common {
/* Register a callback which removes each document/folder from the fulltext index
* The callback must return null otherwise the removal will be canceled.
*/
static function removeFromIndex($arr, $object) { /* {{{ */
$fulltextservice = $arr[0];
$lucenesearch = $fulltextservice->Search();
$hit = null;
if($object->isType('document'))
$hit = $lucenesearch->getDocument($object->getID());
elseif($object->isType('folder'))
$hit = $lucenesearch->getFolder($object->getID());
if($hit) {
$index = $fulltextservice->Indexer();
$index->delete($hit->id);
$index->commit();
}
return null;
} /* }}} */
static function removePreviews($arr, $document) { /* {{{ */
$previewer = $arr[0];
$previewer->deleteDocumentPreviews($document);
return null;
} /* }}} */
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$folder = $this->params['folder'];
$fulltextservice = $this->params['fulltextservice'];
/* Get the folder id and name before removing the folder */
$foldername = $folder->getName();
$folderid = $folder->getID();
if(false === $this->callHook('preRemoveFolder')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preRemoveFolder_failed';
return false;
}
$result = $this->callHook('removeFolder', $folder);
if($result === null) {
if($fulltextservice && ($index = $fulltextservice->Indexer())) {
/* Register a callback which is called by SeedDMS_Core when a folder
* or document is removed. The second parameter passed to this callback
* is the document or folder to be removed.
*/
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_RemoveFolder::removeFromIndex', array($fulltextservice));
$dms->addCallback('onPreRemoveFolder', 'SeedDMS_Controller_RemoveFolder::removeFromIndex', array($fulltextservice));
}
/* Register another callback which removes the preview images of the document */
$previewer = new SeedDMS_Preview_Previewer($settings->_cacheDir);
$dms->addCallback('onPreRemoveDocument', 'SeedDMS_Controller_RemoveFolder::removePreviews', array($previewer));
if (!$folder->remove()) {
$this->errormsg = 'error_occured';
return false;
}
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_removeFolder_failed';
return false;
}
if(false === $this->callHook('postRemoveFolder')) {
}
return true;
} /* }}} */
}

View File

@ -1,131 +0,0 @@
<?php
/**
* Implementation of ReviewDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for reviewing a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2023 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ReviewDocument extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$content = $this->params['content'];
$reviewtype = $this->params['type'];
$reviewstatus = $this->params['status'];
$reviewcomment = $this->params['comment'];
$reviewfile = $this->params['file'];
$reviewgroup = $this->params['group'];
$overallStatus = $content->getStatus();
$this->oldstatus = $overallStatus['status'];
$this->newstatus = $this->oldstatus;
if(!$this->callHook('preReviewDocument', $content)) {
}
$result = $this->callHook('reviewDocument', $content);
if($result === null) {
if ($reviewtype == "ind") {
$reviewLogID = $content->setReviewByInd($user, $user, $reviewstatus, $reviewcomment, $reviewfile);
} elseif($reviewtype == "grp") {
$reviewLogID = $content->setReviewByGrp($reviewgroup, $user, $reviewstatus, $reviewcomment, $reviewfile);
} else {
$this->errormsg = "review_wrong_type";
return false;
}
if($reviewLogID === false || 0 > $reviewLogID) {
$this->errormsg = "review_update_failed";
return false;
}
}
$result = $this->callHook('reviewUpdateDocumentStatus', $content);
if($result === null) {
if($reviewstatus == -1) {
$this->newstatus = S_REJECTED;
if($content->setStatus(S_REJECTED, $reviewcomment, $user)) {
if(isset($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'] as $hookObj) {
if (method_exists($hookObj, 'postReviewDocument')) {
$hookObj->postReviewDocument(null, $content, S_REJECTED);
}
}
}
}
} else {
$docReviewStatus = $content->getReviewStatus();
if (is_bool($docReviewStatus) && !$docReviewStatus) {
$this->errormsg = "cannot_retrieve_review_snapshot";
return false;
}
$reviewCT = 0;
$reviewTotal = 0;
foreach ($docReviewStatus as $drstat) {
if ($drstat["status"] == 1) {
$reviewCT++;
}
if ($drstat["status"] != -2) {
$reviewTotal++;
}
}
// If all reviews have been received and there are no rejections, retrieve a
// count of the approvals required for this document.
if ($reviewCT == $reviewTotal) {
$docApprovalStatus = $content->getApprovalStatus();
if (is_bool($docApprovalStatus) && !$docApprovalStatus) {
$this->errormsg = "cannot_retrieve_approval_snapshot";
return false;
}
$approvalCT = 0;
$approvalTotal = 0;
foreach($docApprovalStatus as $dastat) {
if($dastat["status"] == 1) {
$approvalCT++;
}
if($dastat["status"] != -2) {
$approvalTotal++;
}
}
// If the approvals received is less than the approvals total, then
// change status to pending approval.
if($approvalCT < $approvalTotal) {
$this->newstatus = S_DRAFT_APP;
} else {
// Otherwise, change the status to released.
$this->newstatus = S_RELEASED;
}
if($content->setStatus($this->newstatus, getMLText("automatic_status_update"), $user)) {
if(isset($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'])) {
foreach($GLOBALS['SEEDDMS_HOOKS']['reviewDocument'] as $hookObj) {
if (method_exists($hookObj, 'postReviewDocument')) {
$hookObj->postReviewDocument(null, $content, $this->newstatus);
}
}
}
}
}
}
}
if(!$this->callHook('postReviewDocument', $content)) {
}
return true;
} /* }}} */
}

View File

@ -1,143 +0,0 @@
<?php
/**
* Implementation of ReviseDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ReviseDocument extends SeedDMS_Controller_Common {
public $oldstatus;
public $newstatus;
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$document = $this->params['document'];
$content = $this->params['content'];
$revisionstatus = $this->params['revisionstatus'];
$revisiontype = $this->params['revisiontype'];
$group = $this->params['group'];
$comment = $this->params['comment'];
$overallStatus = $content->getStatus();
$this->oldstatus = $overallStatus['status'];
$this->newstatus = $this->oldstatus;
/* if set to true, a single reject will reject the doc. If set to false
* all revisions will be collected first and afterwards the doc is rejected
* if one has rejected it. So in the very end the doc is rejected, but
* doc remainѕ in S_IN_REVISION until all have revised the doc
*/
$onevotereject = $this->params['onevotereject'];
/* Get the document id and name before removing the document */
$docname = $document->getName();
$documentid = $document->getID();
if(!$this->callHook('preReviseDocument', $content)) {
}
$result = $this->callHook('reviseDocument', $content);
if($result === null) {
if ($revisiontype == "ind") {
if(0 > $content->setRevision($user, $user, $revisionstatus, $comment)) {
$this->error = 1;
$this->errormsg = "revision_update_failed";
return false;
}
} elseif ($revisiontype == "grp") {
if(0 > $content->setRevision($group, $user, $revisionstatus, $comment)) {
$this->error = 1;
$this->errormsg = $ll."revision_update_failed";
return false;
}
}
}
/* Check to see if the overall status for the document version needs to be
* updated.
*/
$result = $this->callHook('reviseUpdateDocumentStatus', $content);
if($result === null) {
if ($onevotereject && $revisionstatus == -1){
$this->newstatus = S_NEEDS_CORRECTION;
if(!$content->setStatus(S_NEEDS_CORRECTION,$comment,$user)) {
$this->error = 1;
$this->errormsg = "revision_update_failed";
return false;
}
} else {
$docRevisionStatus = $content->getRevisionStatus();
if (is_bool($docRevisionStatus) && !$docRevisionStatus) {
$this->error = 1;
$this->errormsg = "cannot_retrieve_revision_snapshot";
return false;
}
$revisionok = 0;
$revisionnotok = 0;
$revisionTotal = 0;
foreach ($docRevisionStatus as $drstat) {
if ($drstat["status"] == 1) {
$revisionok++;
}
if ($drstat["status"] == -1) {
$revisionnotok++;
}
if ($drstat["status"] != -2) {
$revisionTotal++;
}
}
// If all revisions have been done and there are no rejections,
// then release the document. If all revisions have been done but some
// of them were rejections then documents needs correction.
// Otherwise put it back into revision workflow
if ($revisionok == $revisionTotal) {
$this->newstatus=S_RELEASED;
if ($content->finishRevision($user, $this->newstatus, 'Finished revision workflow', getMLText("automatic_status_update"))) {
if(!$this->callHook('finishReviseDocument', $content)) {
}
}
} elseif (($revisionok + $revisionnotok) == $revisionTotal) {
$this->newstatus=S_NEEDS_CORRECTION;
// if ($content->finishRevision($user, $this->newstatus, 'Finished revision workflow', getMLText("automatic_status_update"))) {
if(!$content->setStatus($this->newstatus,$comment,$user)) {
$this->error = 1;
$this->errormsg = "revision_update_failed";
return false;
}
} else {
$this->newstatus=S_IN_REVISION;
if(!$content->setStatus($this->newstatus,$comment,$user)) {
$this->error = 1;
$this->errormsg = "revision_update_failed";
return false;
}
}
}
}
if(!$this->callHook('postReviseDocument', $content)) {
}
return true;
}
}

View File

@ -1,56 +0,0 @@
<?php
/**
* Implementation of Role manager controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for role manager
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_RoleMgr extends SeedDMS_Controller_Common {
public function run() {
}
public function addrole() {
$dms = $this->params['dms'];
$name = $this->params['name'];
$role = $this->params['role'];
return($dms->addRole($name, $role));
}
public function removerole() {
$roleobj = $this->params['roleobj'];
return $roleobj->remove();
}
public function editrole() {
$dms = $this->params['dms'];
$name = $this->params['name'];
$role = $this->params['role'];
$roleobj = $this->params['roleobj'];
$noaccess = $this->params['noaccess'];
if ($roleobj->getName() != $name)
$roleobj->setName($name);
if ($roleobj->getRole() != $role)
$roleobj->setRole($role);
$roleobj->setNoAccess($noaccess);
return true;
}
}

View File

@ -1,53 +0,0 @@
<?php
/**
* Implementation of TransferDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2017 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2017 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_TransferDocument extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$document = $this->params['document'];
$newuser = $this->params['newuser'];
$folder = $document->getFolder();
if(false === $this->callHook('preTransferDocument')) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preTransferDocument_failed';
return null;
}
$result = $this->callHook('transferDocument', $document);
if($result === null) {
if (!$document->transferToUser($newuser)) {
return false;
} else {
if(false === $this->callHook('postTransferDocument')) {
}
}
}
return true;
}
}

View File

@ -1,68 +0,0 @@
<?php
/**
* Implementation of Transmittal Download controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a transmittal
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_TransmittalDownload extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$user = $this->params['user'];
$transmittal = $this->params['transmittal'];
$items = $transmittal->getItems();
if($items) {
include("../inc/inc.ClassDownloadMgr.php");
$downmgr = new SeedDMS_Download_Mgr();
if($extraheader = $this->callHook('extraDownloadHeader'))
$downmgr->addHeader($extraheader);
foreach($items as $item) {
$content = $item->getContent();
$document = $content->getDocument();
if ($document->getAccessMode($user) >= M_READ) {
$extracols = $this->callHook('extraDownloadColumns', $document);
$filename = $this->callHook('filenameDownloadItem', $content);
if($rawcontent = $this->callHook('rawcontent', $content)) {
$downmgr->addItem($content, $extracols, $rawcontent, $filename);
} else
$downmgr->addItem($content, $extracols, null, $filename);
}
}
$filename = tempnam(sys_get_temp_dir(), 'transmittal-download-');
if($filename) {
if($downmgr->createArchive($filename)) {
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filename));
header("Content-Disposition: attachment; filename=\"export-" .date('Y-m-d') . ".zip\"");
header("Content-Type: application/zip");
header("Cache-Control: must-revalidate");
readfile($filename);
} else {
}
unlink($filename);
}
exit;
}
}
}

View File

@ -1,114 +0,0 @@
<?php
/**
* Implementation of UpdateDocument controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_UpdateDocument extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$name = $this->getParam('name');
$comment = $this->getParam('comment');
/* Call preUpdateDocument early, because it might need to modify some
* of the parameters.
*/
if(false === $this->callHook('preUpdateDocument', $this->params['document'])) {
if(empty($this->errormsg))
$this->errormsg = 'hook_preUpdateDocument_failed';
return null;
}
$comment = $this->getParam('comment');
$dms = $this->params['dms'];
$user = $this->params['user'];
$document = $this->params['document'];
$settings = $this->params['settings'];
$fulltextservice = $this->params['fulltextservice'];
$folder = $this->params['folder'];
$userfiletmp = $this->getParam('userfiletmp');
$userfilename = $this->getParam('userfilename');
$filetype = $this->getParam('filetype');
$userfiletype = $this->getParam('userfiletype');
$reviewers = $this->getParam('reviewers');
$approvers = $this->getParam('approvers');
$recipients = $this->getParam('recipients');
$reqversion = $this->getParam('reqversion');
$comment = $this->getParam('comment');
$attributes = $this->getParam('attributes');
$workflow = $this->getParam('workflow');
$maxsizeforfulltext = $this->getParam('maxsizeforfulltext');
$initialdocumentstatus = $this->getParam('initialdocumentstatus');
$content = $this->callHook('updateDocument');
if($content === null) {
$filesize = SeedDMS_Core_File::fileSize($userfiletmp);
if($contentResult=$document->addContent($comment, $user, $userfiletmp, utf8_basename($userfilename), $filetype, $userfiletype, $reviewers, $approvers, 0, $attributes, $workflow, $initialdocumentstatus)) {
if ($this->hasParam('expires')) {
if($document->setExpires($this->getParam('expires'))) {
} else {
}
}
if(!empty($recipients['i'])) {
foreach($recipients['i'] as $uid) {
if($u = $dms->getUser($uid)) {
$res = $contentResult->getContent()->addIndRecipient($u, $user);
}
}
}
if(!empty($recipients['g'])) {
foreach($recipients['g'] as $gid) {
if($g = $dms->getGroup($gid)) {
$res = $contentResult->getContent()->addGrpRecipient($g, $user);
}
}
}
$content = $contentResult->getContent();
} else {
$this->errormsg = 'error_update_document';
$result = false;
}
} elseif($result === false) {
if(empty($this->errormsg))
$this->errormsg = 'hook_updateDocument_failed';
return false;
}
if($fulltextservice && ($index = $fulltextservice->Indexer()) && $content) {
$idoc = $fulltextservice->IndexedDocument($document);
if(false !== $this->callHook('preIndexDocument', $document, $idoc)) {
$lucenesearch = $fulltextservice->Search();
if($hit = $lucenesearch->getDocument((int) $document->getId())) {
$index->delete($hit->id);
}
$index->addDocument($idoc);
$index->commit();
}
}
if(false === $this->callHook('postUpdateDocument', $document, $content)) {
}
return $content;
} /* }}} */
}

View File

@ -1,61 +0,0 @@
<?php
/**
* Implementation of UserListCsv controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for export a list of all users as csv
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_UserListCsv extends SeedDMS_Controller_Common {
public function run() { /* {{{ */
$dms = $this->params['dms'];
$user = $this->params['user'];
$settings = $this->params['settings'];
$group = $this->params['group'];
if($group) {
$allUsers = $group->getUsers();
} else {
$allUsers = $dms->getAllUsers($settings->_sortUsersInList);
}
$m = 0;
foreach($allUsers as $u) {
$m = max($m, count($u->getGroups()));
}
$fp = fopen("php://temp/maxmemory", 'r+');
$header = array('login', 'passenc', 'name', 'email', 'comment', 'role', 'quota', 'homefolder', 'hidden', 'disabled');
for($i=1; $i<=$m; $i++)
$header[] = 'group_'.$i;
fputcsv($fp, $header, ';');
foreach($allUsers as $u) {
$data = array($u->getLogin(), $u->getPwd(), $u->getFullName(), $u->getEmail(), $u->getComment(), $u->isAdmin() ? 'admin' : ($u->isGuest() ? 'guest' : 'user'), $u->getQuota(), $u->getHomeFolder() ? $u->getHomeFolder() : '', $u->isHidden() ? '1' : 0, $u->isDisabled() ? '1' : '0');
foreach($u->getGroups() as $g)
$data[] = $g->getName();
fputcsv($fp, $data, ';');
}
$efilename = 'userlist-'.date('Ymd-His').'.csv';
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
// header("Content-Length: " . filesize($name));
fseek($fp, 0);
fpassthru($fp);
fclose($fp);
return true;
} /* }}} */
}

View File

@ -1,71 +0,0 @@
<?php
/**
* Implementation of ViewOnline controller
*
* @category DMS
* @package SeedDMS
* @license GPL 2
* @version @version@
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
/**
* Class which does the busines logic for downloading a document
*
* @category DMS
* @package SeedDMS
* @author Uwe Steinmann <uwe@steinmann.cx>
* @copyright Copyright (C) 2010-2013 Uwe Steinmann
* @version Release: @package_version@
*/
class SeedDMS_Controller_ViewOnline extends SeedDMS_Controller_Common {
public function run() {
$dms = $this->params['dms'];
$settings = $this->params['settings'];
$type = $this->params['type'];
switch($type) {
case "version":
$version = $this->params['version'];
$document = $this->params['document'];
if($version < 1) {
$content = $this->callHook('documentLatestContent', $document);
if($content === null)
$content = $document->getLatestContent();
} else {
$content = $this->callHook('documentContent', $document, $version);
if($content === null)
$content = $document->getContentByVersion($version);
}
if (!is_object($content)) {
$this->errormsg = 'invalid_version';
return false;
}
/* set params['content'] for compatiblity with older extensions which
* expect the content in the controller
*/
$this->params['content'] = $content;
if(null === $this->callHook('version')) {
if(file_exists($dms->contentDir . $content->getPath())) {
header("Content-Type: " . $content->getMimeType());
$efilename = rawurlencode($content->getOriginalFileName());
if (!isset($settings->_viewOnlineFileTypes) || !is_array($settings->_viewOnlineFileTypes) || !in_array(strtolower($content->getFileType()), $settings->_viewOnlineFileTypes)) {
header("Content-Disposition: attachment; filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
} else {
header("Content-Disposition: filename=\"" . $efilename . "\"; filename*=UTF-8''".$efilename);
}
header("Cache-Control: must-revalidate");
header("ETag: ".$content->getChecksum());
sendFile($dms->contentDir.$content->getPath());
}
}
break;
}
return true;
}
}

View File

@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
# This command retrieves the strings that need to be translated # This command retrieves the strings that need to be translated
sgrep -o "%r\n" '"getMLText(\"" __ "\""' */*.php views/bootstrap/*.php |sort|uniq -c sgrep -o "%r\n" '"getMLText(\"" __ "\""' */*.php|sort|uniq -c

View File

@ -1,7 +1,7 @@
<?php <?php
/* Determine all languages keys used in the php files */ /* Determine all languages keys used in the php files */
$output = array(); $output = array();
if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php views/bootstrap/*.php|sort|uniq -c', $output)) { if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php|sort|uniq -c', &$output)) {
$allkeys = array(); $allkeys = array();
foreach($output as $line) { foreach($output as $line) {
$data = explode(' ', trim($line)); $data = explode(' ', trim($line));
@ -9,9 +9,8 @@ if(exec('sgrep -o "%r\n" \'"tMLText(\"" __ "\""\' */*.php views/bootstrap/*.php|
} }
} }
$languages = array('ar_EG', 'bg_BG', 'ca_ES', 'cs_CZ', 'de_DE', 'en_GB', 'es_ES', 'fr_FR', 'hu_HU', 'it_IT', 'nl_NL', 'pl_PL', 'pt_BR', 'ro_RO', 'ru_RU', 'sk_SK', 'sv_SE', 'tr_TR', 'zh_CN', 'zh_TW');
/* Reading languages */ /* Reading languages */
foreach($languages as $lang) { foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
include('languages/'.$lang.'/lang.inc'); include('languages/'.$lang.'/lang.inc');
ksort($text); ksort($text);
$langarr[$lang] = $text; $langarr[$lang] = $text;
@ -21,7 +20,7 @@ foreach($languages as $lang) {
echo "List of missing keys\n"; echo "List of missing keys\n";
echo "-----------------------------\n"; echo "-----------------------------\n";
foreach(array_keys($allkeys) as $key) { foreach(array_keys($allkeys) as $key) {
foreach($languages as $lang) { foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
if(!isset($langarr[$lang][$key])) { if(!isset($langarr[$lang][$key])) {
echo "Missing key '".$key."' in language ".$lang."\n"; echo "Missing key '".$key."' in language ".$lang."\n";
} }
@ -32,7 +31,7 @@ echo "\n";
/* Check for phrases not used anymore */ /* Check for phrases not used anymore */
echo "List of superflous keys\n"; echo "List of superflous keys\n";
echo "-----------------------------\n"; echo "-----------------------------\n";
foreach($languages as $lang) { foreach(array('English', 'German', 'Italian', 'Slovak', 'Czech') as $lang) {
$n = 0; $n = 0;
foreach($langarr[$lang] as $key=>$value) { foreach($langarr[$lang] as $key=>$value) {
if(!isset($allkeys[$key])) { if(!isset($allkeys[$key])) {
@ -46,8 +45,8 @@ foreach($languages as $lang) {
exit; exit;
$fpout = fopen('php://stdout', 'w'); $fpout = fopen('php://stdout', 'w');
foreach(array_keys($langarr['en_GB']) as $key) { foreach(array_keys($langarr['English']) as $key) {
$data = array($key, $langarr['en_GB'][$key], $langarr['de_DE'][$key]); $data = array($key, $langarr['English'][$key], $langarr['German'][$key]);
fputcsv($fpout, $data); fputcsv($fpout, $data);
} }
?> ?>

View File

@ -1,206 +0,0 @@
Commands for converting documents
----------------------------------
This file contains commands for converting different document types
into
* text (for fulltext search)
* png (for preview images)
* pdf (for pdf documents)
Such conversions may not necessarily output an excact equivalent of
the input file, but outputs a suitable representation, e.g.
converting an mp3 file into text may output the metadata or even the
lyrics of the song. Converting it into a preview image may result
in a picture of the album cover.
Please note, that when ever a command outputs anything to stderr,
this will considered as a failure of the command. Most command line
programs have a parameter (.e.g. `-q`) to suppress such an output.
If you run php-fpm you may encounter problems with charsets based on
UTF-8. Programms like `catdoc` read LANG from the environment to
set the correct encoding of the output. php-fpm often clears the
environment and programms like `catdoc` will not longer output any
UTF-8 chars. In such a case you may want to set `clear_env=no` in
php-fpm's configuration. On Debian this is done in the file
`/etc/php/<php version>/fpm/pool.d/www.conf`. Search for `clear_env`.
Conversion to text for fulltext search
=======================================
text/plain
text/csv
application/csv
cat '%s'
application/pdf
pdftotext -q -nopgbrk %s - | sed -e 's/ [a-zA-Z0-9.]\{1\} / /g' -e 's/[0-9.]//g'
If pdftotext takes too long on large document you may want to pass parameter
-l to specify the last page to be converted. -q is for suppressing error/warnings
send to stderr
mutool draw -F txt -q -N -o - %s
application/vnd.openxmlformats-officedocument.wordprocessingml.document
docx2txt '%s' -
application/msword
catdoc %s
application/vnd.oasis.opendocument.text
odt2txt %s
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
xlsx2csv -d tab %s
application/vnd.ms-excel
xls2csv -d tab %s
text/html
html2text %s
Many office formats
unoconv -d document -f txt --stdout '%s'
Apache Tika is another option for creating plain text from various document
types. Just use curl to send the document to your tika server and get the
plain text in return.
curl -s -T '%s' http://localhost:9998/tika --header 'Accept: text/plain'
Conversion to pdf for pdf preview
==================================
text/plain
text/csv
application/csv
application/vnd.oasis.opendocument.text
application/msword
application/vnd.wordperfect
text/rtf
unoconv -d document -f pdf --stdout -v '%f' > '%o'
image/png
image/jpg
image/jpeg
convert -density 300 '%f' 'pdf:%o'
image/svg+xml
cairosvg -f pdf -o '%o' '%f'
application/vnd.ms-powerpoint
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.oasis.opendocument.presentation
unoconv -d presentation -f pdf --stdout -v '%f' > '%o'
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.oasis.opendocument.spreadsheet
unoconv -d spreadsheet -f pdf --stdout -v '%f' > '%o'
message/rfc822
java -jar emailconverter-2.5.3-all.jar '%f' -o '%o'
The emailconverter can be obtained from https://github.com/nickrussler/email-to-pdf-converter
It requires wkhtmltopdf which is part of debian.
text/plain
iconv -c -f utf-8 -t latin1 '%f' | a2ps -1 -q -a1 -R -B -o - - | ps2pdf - -
The parameter `-q` is important because a2ps sends some statistical
data to stderr, which makes SeedDMS believe the command has failed.
application/x-xopp
xournalpp -p "%o" "%f"
Converting from application/x-xopp to pdf only works if the xopp file
does not use a pdf document as a background, because this pdf is not
stored in the xopp fіle.
Conversion to png for preview images
=====================================
If you have problems running convert on PDF documents then read this page
https://askubuntu.com/questions/1081895/trouble-with-batch-conversion-of-png-to-pdf-using-convert
It basically instructs you to comment out the line
<policy domain="coder" rights="none" pattern="PDF" />
in /etc/ImageMagick-6/policy.xml
convert determines the format of the converted image from the extension of
the output filename. SeedDMS usually sets a propper extension when running
the command, but nevertheless it is good practice to explicitly set the output
format by prefixing the output filename with 'png:'. This is of course always
needed if the output goes to stdout.
image/jpg
image/jpeg
image/png
convert -resize %wx '%f' 'png:%o'
image/svg+xml
cairosvg -f png --output-width %w -o '%o' '%f'
text/plain
convert -density 100 -resize %wx 'text:%f[0]' 'png:%o'
application/pdf
gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q '%f' | convert -resize %wx png:- '%o'
convert -density 100 -resize %wx '%f[0]' 'png:%o'
mutool draw -F png -w %w -q -N -o '%o' '%f' 1
pdftocairo '%f' -png -singlefile -scale-to-x %w -scale-to-y -1 - > '%o'
pdftocairo needs to output to stdout because the output file name passed
to pdftocairo will be suffixed with png
application/postscript
convert -density 100 -resize %wx '%f[0]' 'png:%o'
text/plain
iconv -c -f utf-8 -t latin1 '%f' | a2ps -1 -q -a1 -R -B -o - - | gs -dBATCH -dNOPAUSE -sDEVICE=png16m -dFirstPage=1 -dLastPage=1 -dPDFFitPage -r72x72 -sOutputFile=- -q - | convert -resize %wx png:- 'png:%o'
On Linux systems you will have to set the desired value in /etc/papersize for a2ps
e.g. a4, or letter. Unfortunately, a2ps cannot process utf-8 encoded files. That's
why the input needs to be recoded with iconv or recode.
application/msword
application/vnd.oasis.opendocument.spreadsheet
application/vnd.oasis.opendocument.text
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.wordprocessingml.document
text/rtf
application/vnd.ms-powerpoint
text/csv
application/csv
application/vnd.wordperfect
unoconv -d document -e PageRange=1 -f pdf --stdout -v '%f' | gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha -dPDFFitPage -r72x72 -sOutputFile=- -dFirstPage=1 -dLastPage=1 -q - | convert -resize %wx png:- 'png:%o'
video/webm
video/mp4
This will take 12th frame of a video and converts into a png. It requires
ffmpeg to be installed.
convert -resize %wx "%f[12]" "png:%o"
You may as well use ffmpeg right away
ffmpeg -i "%f" -ss 00:00:02 -frames:v 1 -loglevel quiet -vf scale=%w:-1 -f apng "%o"
audio/mpeg
sox "%f" -n spectrogram -x 600 -Y 550 -r -l -o - | convert -resize %wx png:- "png:%o"
application/x-xopp
xournalpp -i "%o" --export-png-width=%w "%f"
Converting from application/x-xopp to png only works if the xopp file
does not use a pdf document as a background, because this pdf is not
stored in the xopp fіle.

View File

@ -1,95 +0,0 @@
Layout of installation
=======================
SeedDMS allows various kinds of installations with very individual layouts
on disc. The proposed layout till version 5.1.6 was as the following:
seeddms51x ---+--- data
|
+--- pear
|
+--- seeddms-5.1.x
|
+--- www -> seeddms-5.1.x
'data' contains all document files, the sqlite database (if used), the full text
data, the log files, and the cached preview images.
'pear' contains all PEAR packages including the four SeedDMS packages SeedDMS_Core,
SeedDMS_Lucene, SeedDMS_Preview, SeedDMS_SQLiteFTS.
'seeddms-5.1.x' are the sources of seeddms and 'www' being a link on it.
This layout has disadvantages when updating the source of seeddms, because
the directories 'conf' and 'ext' had to be moved from 'seeddms-5.1.x' to
'seeddms-5.1.(x+1)'. 'conf' was also visible over the web unless it was
protected by an .htaccess file. The .htaccess file has been shipped, but it
is far better to keep senѕitive data out of the document root in the first
place.
The new layout mostly retains that structure but uses more soft links to place
the local data outside of 'seeddms-5.1.x' which makes updating a lot easier
and moves the configuration out of the document root.
As MS Windows does not support soft links, this change will only apply to Linux/Unix
systems. MS Windows users just skip all the soft links and set seeddms-5.1.x
as the document root. The new layout is the following:
seeddms51x ---+--- data --+-- log
| |
| +-- cache
| |
| +-- 1048576
| |
| +-- ...
|
+--- pear
|
+--- conf
|
+--- seeddms-5.1.x
|
+--- seeddms -> seeddms-5.1.x
|
+--- www --+-- inc -> ../seeddms/inc
|
+-- op -> ../seeddms/op
|
+-- out -> ../seeddms/out
|
+-- views -> ../seeddms/views
|
+-- controllers -> ../seeddms/controllers
|
+-- styles -> ../seeddms/styles
|
+-- languages -> ../seeddms/languages
|
+-- webdav -> ../seeddms/webdav
|
+-- restapi -> ../seeddms/restapi
|
+-- pdfviewer -> ../seeddms/pdfviewer
|
+-- index.php -> ../seeddms/index.php
|
+-- ext
In order to convert to this layout you need to do the following in the seeddms51x
directory (replace the 'x' in '5.1.x' with the correct number):
ln -s seeddms-5.1.x seeddms
mv www/conf .
mv seeddms-5.1.x/ext www
cd www
rm inc op out views controllers styles languages webdav restapi pdfviewer index.php
ln -s ../seeddms/inc
ln -s ../seeddms/op
ln -s ../seeddms/out
ln -s ../seeddms/views
ln -s ../seeddms/controllers
ln -s ../seeddms/styles
ln -s ../seeddms/languages
ln -s ../seeddms/webdav
ln -s ../seeddms/restapi
ln -s ../seeddms/pdfviewer
ln -s ../seeddms/index.php

View File

@ -1,53 +0,0 @@
Extensions in SeedDMS
=====================
Since verson 5.0.0 SeedDMS can be extended by extensions. Extensions
can hook up functions into certain operations, e.g.
uploading, removing or displaying a document. They can also be
used to modify some of the internal variables like the list of
translations and they can even replace classes in the core of
seeddms and hook up functions into certain operations in the core.
All extensions are located in the folder 'ext'. Each extension
has its own folder named by the name of the extension. The central
configuration of an extension is stored in conf.php.
The configuration sets the file and classname which is loaded
during initialization of the extension. The class has to have
a method init() which is called with any page request. The
configuration itself is cached and must be updated within
the extension manager if it was changed.
The integration into SeedDMS is done by hooks, class and file
overloading. SeedDMS manages
a globally available array of hooks ($GLOBALS['SEEDDMS_HOOKS']).
This array has the elements 'view' and 'controller'. All entries
in those array elements contain instances of self defined classes
containing the hook methods. For setting up the hooks in the view
'viewFolder' the following code is needed.
$GLOBALS['SEEDDMS_HOOKS']['view']['viewFolder'][] = new SeedDMS_ExtExample_ViewFolder;
class SeedDMS_ExtExample_ViewFolder {
...
};
The same approach is implemented for hooks called from the controller
logic (the op/op.*.php files).
$GLOBALS['SEEDDMS_HOOKS']['controller']['removeFolder'][] = new SeedDMS_ExtExample_RemoveFolder;
class SeedDMS_ExtExample_RemoveFolder {
...
};
Based on these two variants of adding hooks to the seeddms application code,
the seeddms core can be extended by implementing the controller hook 'initDMS'
which is called right after the class SeedDMS_Core_DMS has been initiated.
Beside hooks and callbacks another way of modifying seeddms is given
by overloading the files in the directory 'views' and 'controllers'. Both
directories contain class files with a single class for either running
controller or view code. If an extension provides those file in its
own extension dir, they will be used instead of the files shipped with
seeddms.

View File

@ -1,18 +0,0 @@
Adding authentication failure check for fail2ban
=================================================
You will have to use 5.1.10 for this to work.
Add a filter /etc/fail2ban/filter.d/seeddms.conf with the content
[Definition]
failregex = \[error\] -- \(<HOST>\) op.Login login failed
then configure a new jail in /etc/fail2ban/jail.d/seeddms.conf
[seeddms]
enabled = yes
port = http,https
filter = seeddms
logpath = /home/www-data/seeddms-demo/data/log/*.log

View File

@ -1,216 +0,0 @@
Hooks
======
Attention: the api for hooks isn't stable yet!
Hooks in SeedDMS are user definied methods which are being called by
the application. The SeedDMS Core also has hooks which are being
called from the core itself. They are not subject of this document.
The SeedDMS application distinguishes between
* view hooks and
* controller hooks
view hooks usually return some html output which is send to the browser
and either replaces the default output or adds additional information.
A view hooks which returns null will be considered as not being called
at all. If the hook is expected to return something, it must be either
a string or an array of strings.
controller hooks implement additional functions which either replace
existing functions or add new ones. If such a hook returns null then
this is treated as if the hook was not called. If the hook returns
false it will prevent other hooks implementing the same function from
being called. All other return values will not stop other hooks from
being called. A controller hook may set the error msg of the calling
controller.
Currently available controller hooks
------------------------------------
AddDocument::preAddDocument
Called before a new document will be added
If the hook returns false the document will not be added and the error msg
set by the hook will be issued. This hook is called before the parameters
are fetch from the controller. Therefore it is possible to modify them
in this hook.
AddDocument::addDocument
Called when the new document is to be added
This hook can be used to replace the code for adding a document. In
that case it must return a document or false. If
the hook does not return null, the original code for adding the
document will be skipped.
AddDocument::postAddDocument
Called after a new document has been added
This hook will be called after a document was added, both by the
original code and within the hook addDocument. The hook is not called
if adding the document failed. The document will be passed to the hook.
The return value of this hook should always be null.
AddDocument::preIndexDocument
Called before a new document will be indexed
This hook will be called after the document was added and before
the hook postAddDocument. The parameters passed
are the document and the indexed document. Returning false will prevent
the document from being indexed.
EditDocument::editDocumentAttribute
Called for each custom document attribute
This hook will be called for each custom attribute to ouput the form entry.
The parameters passed are the document and the attribute definition.
Returning an empty array will prevent the attribute from being show.
Returning an array with two elements will pass those element to the formField
method. A returned string will be output as is.
EditDocument::addDocumentAttributes
Called after all custom document attributes has been output
This hook will be called right after the document attributes have been shown.
The return value is either an array with two elements or a string.
The string will be output as is, the array will be passed to the method formField.
UpdateDocument::preUpdateDocument
Called before a new document will be updated
If the hook returns false the document will not be updated and the error msg
set by the hook will be issued. This hook is called before the parameters
are fetch from the controller. Therefore it is possible to modify them
in this hook.
UpdateDocument::updateDocument
Called when the document is to be updated
This hook can be used to replace the code for updating a document. In
that case it must return a document content or false. If
the hook returns null, the original code for adding the
document will be executed.
UpdateDocument::postUpdateDocument
Called after a new document has been updated
This hook will be called after a document was updated, both by the
original code and within the hook addDocument.
The document and content will be passed to the hook.
The return value of this hook should always be null.
UpdateDocument::preIndexDocument
Called before an updated document will be indexed
This hook will be called after the document was updated and before
the hook postUpdateDocument. The parameters passed
are the document and the indexed document. Returning false will prevent
the document from being indexed.
RemoveDocument::preRemoveDocument
Called before a document will be removed
If the hook returns false the document will not be removed and the error msg
set by the hook will be issued.
RemoveDocument::removeDocument
Called when the document is to be removed
If the hook returns null the
regular document removal will happen.
RemoveDocument::postRemoveDocument
Called after a document was removed
This hook will be called after a document was removed, both by the
original code and within the hook removeDocument. It will not be
called if removing the document failed.
The return value of this hook should always be null.
RemoveFolder::preRemoveFolder
Called before a folder will be removed
If the hook returns false the folder will not be removed and the error msg
set by the hook will be issued.
RemoveFolder::removeFolder
Called for removing the folder.
If the hook returns null the regular folder removal will happen.
Keep in mind, that the hook function must also update the
full text index.
RemoveFolder::postRemoveFolder
Called after a document was removed
This hook will be called after a folder was removed, both by the
original code and within the hook removeFolder. It will not be
called if removing the folder failed.
The return value of this hook should always be null.
EditFolder::preEditFolder
Called before a folder will be updated
If the hook returns false the folder will not be updated and the error msg
set by the hook will be issued. This hook is called before the parameters
are fetch from the controller. Therefore it is possible to modify them
in this hook.
EditFolder::EditFolder
Called when the folder is to be updated
This hook can be used to replace the code for updating a folder. If
the hook returns null, the original code for adding the
document will be executed.
EditFolder::postEditFolder
Called after a folder was updated
This hook will be called after a folder was updated, both by the
original code and within the hook removeFolder. It will not be
called if updating the folder failed.
The return value of this hook should always be null.
TransferDocument::preTransferDocument
TransferDocument::transferDocument
TransferDocument::postTransferDocument
ViewOnline::version
Called when a document is downloaded for online view
Download::version
Called when a document is downloaded for saving on disk
Login::preLogin
Called before a user is logged in
Login::authenticate
Called before any other authentication is done
If this hooks returns a user, no other authentication will be done.
If it returns false, the login fails as well.
Login::restrictLogin
Called right before the user is considered to be logged in
This hook can contain a last check which keeps the user from being
logged in. Return false to stop login. The authenticated user is
passed to the hook.
Login::postLogin
Called after user in fully logged in
The logged in user is passed to the hook.
Login::loginFailed
Called if authentication failed
Logout::postLogout
Called after user is logged out
IndexDocument::preIndexDocument
Currently available view hooks
------------------------------------

View File

@ -1,601 +0,0 @@
SeedDMS Installation Instructions
==================================
REQUIREMENTS
============
SeedDMS is a web-based application written in PHP. It uses MySQL,
SQLite3 or PostgreSQL to manage the documents that were uploaded into
the application. Be aware that PostgreSQL is not very well tested.
Make sure you have PHP >= 8.2 and MySQL 5 or higher installed. SeedDMS
will work with PHP running in CGI-mode as well as running as a module under
apache.
Here is a detailed list of requirements:
1. A web server with at least php 8.2
2. A mysql database, unless you use SQLite
3. The php installation must have support for `pdo_mysql`, `pdo_pgsql` or `pdo_sqlite`,
`php_gd2`, `php_mbstring`, `php_xml`
4. Depending on the configuration the extensions `php_ldap`, `php_mycrypt`,
`php_gmp`, `php_libsodium`, `php_imagick` must be installed
5. Various command line programms to convert files into text for indexing
pdftotext, catdoc, xls2csv or scconvert, cat, id3 (all optional, only needed
for fulltext search)
6. ImageMagic (the convert program) is needed for creating preview images
7. A bunch of packages from Packagist which all ship with the seeddms-quickstart
archive
It is highly recommended to use the quickstart archive
(seeddms-quickstart-x.y.z.tar.gz) because it includes all software packages
(excluding those listed above in item 1. to 6.) for running SeedDMS. Hence,
you still need a working web server with PHP and in addition a mysql or
PostgreSQL database unless you intend to use SQLite.
QUICKSTART
===========
The fastes way to get SeedDMS running is by unpacking the archive
`seeddms-quickstart-x.y.z.tar.gz` on your webserver.
Let's assume you use seeddms-quickstart-5.1.x.tar.gz.
It will create a new directory `seeddms51x` containing everything you
need to run SeedDMS with SQLite3. Even if you intend to use mysql in the
long run it is advisable to first set up SeedDMS with SQLite3 and than
just switch the database.
Setting up the web server
--------------------------
First of all you will need to set up your web server. Here, we will only focus
on apache running on Debian/GNU Linux.
Either let the document root of your web server point to the directory `www`
below `seeddms51x`
DocumentRoot /var/www/seeddms51x/www
or add an alias. For apache this could be like
Alias /seeddms51x /<some directory>/seeddms51x/www
or even
Alias /mydms /<some directory>/seeddms51x/www
Do not set the DocumentRoot or Alias to
the `seeddms51x` directory, because this will allow anybody to access
your `data` and `conf` directory if it is not secured by a .htaccess file.
This is a major security risk.
Make sure that the subdirectory `seeddms51x/data` and the configuration file
`seeddms51/conf/settings.xml` is writeable by your web server. All other
directories can be just readable by your web server, though it is advisable
to even protect them from writing.
Adjusting the configuration of SeedDMS
---------------------------------------
In the next step you need to adjust the configuration file in
`seeddms51x/conf/settings.xml`. Open the file in your favorite text editor
and search for `/home/wwww-data`. Replace that part in any path found with your
base directory where you placed seeddms51x (e.g. /var/www/html/seeddms51x).
Alternatively, you can open the installer with a browser at
http://your-domain/install (if the document root points to
`seeddms51x/www`) or http://your-domain/seeddms51x/install/ (if you have
set an alias like described above).
It will first ask to unlock the installer by creating a file
`ENABLE_INSTALL_TOOL` in the diretory `seeddms51x/conf/`. Change all paths by
replacing `/home/www-data` with your base directory where you put seeddms51x.
Set httpRoot to `/` (if the document root points to `seeddms51x/www`) or
`/seeddms51x` (if you have set an alias `seeddms51x` like described above).
Once your configuration is done,
save it, remove the file `ENABLE_INSTALL_TOOL` and point your browser to
http://your-domain/ or http://your-domain/seeddms51x.
SECURITY CONSIDERATIONS
=======================
You should always access your SeedDMS installation through
a secured https connection, unless you precisly know what you are doing.
SeedDMS ships an `.htaccess` file which already has some common security
http headers set. In order for them to apply you need to activate the
headers module. On Debian/GNU Linux this can be done with
```
a2enmod headers
```
Protect directories with data or configuration
---------------------------------------------
A crucial point when setting up SeedDMS is the propper placement of the
data directory. Do not place it below your document root of your web server!
If you do so, there is a potential way that
attackers can easily access your documents with a regular web browser.
If you cannot place the data directory outside of document root, then either
restrict access to it with an appropriate `.htaccess` file like the following.
The SeedDMS quickstart archive already includes this `.htaccess` file.
```
# line below if for Apache 2.4
<ifModule mod_authz_core.c>
Require all denied
</ifModule>
# line below if for Apache 2.2
<ifModule !mod_authz_core.c>
deny from all
Satisfy All
</ifModule>
# section for Apache 2.2 and 2.4
<ifModule mod_autoindex.c>
IndexIgnore *
</ifModule>
```
Alternatively or in addition you can change
the `contentOffsetDir` in `settings.xml` to something random, but ensure it
is still a valid directory name. If you change contentOffsetDir, then
do not forget to move `data/1048576` to `data/<your random name>`.
Also turn off directory listings in your apache configuration for the
`data` directory.
Securing the configuration file
---------------------------------
The configuration can be fully controlled by any administrator of SeedDMS. This
can be crucial for those configuration options where external commands are
being configured, e.g. for the full text engine or creating preview images.
As a hoster you may not want this configuration options being set by a SeedDMS
administrator. For now you need to make the configuration file `settings.xml`
unwritable for the web server. In that case the SeedDMS administrator can
still see the configuration but will not be able to change it.
Since version 5.1.23 and 6.0.16 of SeedDMS there is some preliminary way to
hide parts of the configuration which makes them unchangeable for the
SeedDMS administrator.
Setting a new encryption key
------------------------------
Though this is not related to setting up the web server environment, it is
important to recreated the encryption key in SeedDMS once SeedDMS is running.
Just open the settings in the admin tools and empty the currently set
encryption key on the tab 'System'. Save the settings and check the key again.
It should be a new one. Save the settings again. The encryption key is
mainly used for creating tokens in HTML forms to prevent CSRF attacks.
UPGRADING FROM A PREVIOUS VERSION OF SEEDDMS
=============================================
As SeedDMS is a smooth continuation of LetoDMS there is no difference
in updating from LetoDMS or SeedDMS.
You have basically two choices to update SeedDMS:
- you install a fresh version of SeedDMS and copy over your data and configuration
- you replace the software in your current installation with a new version
The first option is less interuptive but requires to be able to set up a second
temporary SeedDMS installation, which may not be possible, e.g. because of storage
limitations. It can be the only option if you change servers.
The first update procedure is only needed if the version changes on the minor
or major version number. Changes in the subminor version number will never
include database changes and consequently it is sufficient to use the existing
data directory and database with the new version. Choose the second update
option in this case.
In both cases make sure to have a backup of your data directory, configuration
and database.
Fresh installation and take over of data
-----------------------------------------
The first update option is to set up a new instance of SeedDMS and once
that is running take over the data from your current (old) instance.
1. just do a fresh installation somewhere on your web server and make sure it
works. It is fine to use
SQLite for it, even if your final installation uses MySQL.
2. replace the data directory in your new installation with the data directory
from your current installation. Depending on the size of that directory (and
whether the new installation is on a new server or the old server) you
may either copy, move or place a symbolic link. The content of the data directory
will not be changed during the update. Its even perfectly save to
browse through your documents and download them after finishing the
update. The data directory will not be modified until you actually modify
documents.
3. copy over the configuration `settings.xml` into your new installation. This will
effectively make your new installation use the data from your old installation,
because all paths are still pointing to the old installation.
4. if you use mysql you could as well make a copy of the database to make sure
your current database remains unchanged.
5. modify the `settings.xml` to fit the environment of the new installation.
This will mostly be the
httpRoot, the paths to the installation directory and possibly the database
connection.
6. create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
your browser at http://hostname/seeddms/install
The install tool will detect the version of your current SeedDMS installation
and run the required database updates.
If you update just within the last version number (e.g. from 5.1.6 to 5.1.9),
this step
will not be required because such a subminor version update will never
contain database updates.
Upgrading your current installation
-----------------------------------
Instead of setting up a new installation, you may as well replace the php files
in your current installation with new versions from the quickstart archive.
1. get the SeedDMS quickstart archive `seeddms-quickstart-x.y.z.tar.gz` and
unpack it somewhere on your disc.
2. copy the directory `seeddms-x.y.z` from the unpacked archive into your
current installation and make the link `seeddms` point to this new directory.
3. copy the directory `pear` from the unpacked archive into your current
installation, replacing the existing directory. Make a backup of `pear` before
the replacement if you want to ensure to be able to go back to your old version.
4. you may compare your `conf/settings.xml` file with the shipped version
`conf/settings.xml.template` for new parameters. If you don't do it, the next
time you save the configuration the default values will be used.
5. create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
your browser at http://hostname/seeddms/install
The install tool will detect the version of your current SeedDMS installation
and run the required database updates.
If you update just within the last version number (e.g. from 5.1.6 to 5.1.9),
this step
will not be required because such a subminor version update will never
contain database updates.
THE LONG STORY
================
This section is mostly outdated but may still contain some valueable
information for those trying to understand the installation process.
If you intend to run a single instance of SeedDMS, you are most likely
better off by using the quickstart archive as described above. This
section is mostly for users who wants to know more about the internals
of SeedDMS or do packaging for a software distribution, which already
ships some of the additional software SeedDMS requires.
SeedDMS has changed its installation process with version 3.0.0. This gives
you many more options in how to install SeedDMS. First of all, SeedDMS was
split into a core package (`SeedDMS_Core-<version>.tar.gz`) and the web
application itself (`seeddms-<version>.tar.gz`). The core is a pear package
which could be installed as one. It is responsible for all the database
operations. The web application contains the ui not knowing anything about
the database layout. Second, one SeedDMS installation can be used for
various customer instances by sharing a common source. Starting with
version 3.2.0 a full text search engine has been added. This requires
the zend framework and another pear package `SeedDMS_Lucene-<version>.tar.gz`
which can be downloaded from the SeedDMS web page. Version 4.0.0 show
preview images of documents which requires `SeedDMS_Preview-<version>.tar.gz`.
Finally, SeedDMS has
got a web based installation, which takes care of most of the installation
process.
Before you proceed you have to decide how to install SeedDMS:
1. with multiple instances
2. as a single instance
Both have its pros and cons, but
1. setting up a single instance is easier if you have no shell access to
the web server
2. the installation script is only tested for single instances
Installation for multiple instances shares the same source by many
instances but requires to create links which is not in any case possible
on your web server.
0. Some preparation
-------------------
A common source of problems in the past have been the additional software
packages needed by SeedDMS. Those are the PEAR packages `Log`, `Mail` and
`HTTP_WebDAV_Server` as well as the `Zend_Framework`.
If you have full access to the server running a Linux distribution it is
recommended to install those with your package manager if they are provided
by your Linux distribution. If you cannot install it this way then choose
a directory (preferable not below your web document root), unpack the
software into it and extend the php include path with your newly created
directory. Extending the php include can be either done by modifying
php.ini or adding a line like
> php_value include_path '/home/mypath:.:/usr/share/php'
to your apache configuration or setting the `extraPath` configuration
variable of SeedDMS.
For historical reasons the path to the SeedDMS_Core and SeedDMS_Lucene package
can still be set
in the configuration, which is not recommend anymore. Just leave those
parameters empty.
On Linux/Unix your web server should be run with the environment variable
LANG set to your system default. If LANG=C, then the original filename
of an uploaded document will not be preserved if the filename contains
non ascii characters.
Turn off magic_quotes_gpc in your php.ini, if you are using a php version
below 5.4.
1. Using the installation tool
------------------------------
Unpack seeddms-<version>.tar.gz below the document root of
your web server.
Install `SeedDMS_Preview-<version>.tar.gz` and
`SeedDMS_Core-<version>.tar.gz` either as a regular pear package or
set up a file system structure like pear did somewhere on you server.
For the full text search engine support, you will also
need to install `SeedDMS_Lucene-<version>.tar.gz`.
For the following instructions we will assume a structure like above
and seeddms-<version> being accessible through
http://localhost/seeddms/
* Point you web browser towards http://hostname/seeddms/install/
* Follow the instructions on the page and create a file `ENABLE_INSTALL_TOOL`
in the `conf` directory.
* Create a data directory with the thre sub directories staging, cache
and lucene.
Make sure the data directory is either *not* below your document root
or is protected with a .htaccess file against web access. The data directory
needs to be writable by the web server.
* Clicking on 'Start installation' will show a form with all necessary
settings for a basic installation.
* After saving your settings succesfully you are ready to log in as admin and
continue customizing your installation with the 'Admin Tools'
2. Detailed installation instructions (single instance)
-------------------------------------------------------
You need a working web server with MySQL/PHP5 support and the files
`SeedDMS-<version>.tar.gz`, `SeedDMS_Preview-<version>.tar.gz` and
`SeedDMS_Core-<version>.tgz`. For the
full text search engine support, you will also need to unpack
`SeedDMS_Lucene-<version>.tgz`.
* Unpack all the files in a public web server folder. If you're working on
a host machine your provider will tell you where to upload the files.
If possible, do not unpack the pear packages `SeedDMS_Core-<version>.tgz`,
`SeedDMS_Preview-<version>.tgz` and
`SeedDMS_Lucene-<version>.tgz` below the document root of your web server.
Choose a temporary folder, as the files will be moved in a second.
Create a directory e.g. `pear` in the same directory where you unpacked
seeddms and create a sub directory SeedDMS. Move the content except for the
`tests` directory of all SeedDMS pear
packages into that directory. Please note that `pear/SeedDMS` may not
(and for security reasons should not) be below your document root.
You will end up with a directory structure like the following
> seeddms-<version>
> pear
> SeedDMS
> Core.php
> Core
> Lucene.php
> Lucene
> Preview
> Preview.php
Since they are pear packages they can also be installed with
> pear install SeedDMS_Core-<version>.tgz
> pear install SeedDMS_Lucene-<version>.tgz
> pear install SeedDMS_Preview-<version>.tgz
* The PEAR packages Log and Mail are also needed. They can be downloaded from
http://pear.php.net/package/Log and http://pear.php.net/package/Mail.
Either install it as a pear package
or place it under your new directory 'pear'
> pear
> Log
> Log.php
> Mail
> Mail.php
* The package HTTP_WebDAV_Server is also needed. It can be downloaded from
http://pear.php.net/package/HTTP_WebDAV_Server. Either install it as a
pear package or place it under your new directory 'pear'
> pear
> HTTP
> WebDAV
> Server
> Server.php
If you run PHP in CGI mode, you also need to place a .htaccess file
in the webdav directory with the following content.
RewriteEngine on
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization},last]
* Create a data folder somewhere on your web server including the subdirectories
staging, cache and lucene and make sure they are writable by your web server,
but not accessible through the web.
For security reason the data folder should not be inside the public folders
or should be protected by a .htaccess file. The folder containing the
configuration (settings.xml) must be protected by an .htaccess file like the
following.
> <Files ~ "^settings\.xml">
> Order allow,deny
> Deny from all
> </Files>
If you install SeedDMS for the first time continue with the database setup.
* Create a new database on your web server
e.g. for mysql:
create database seeddms;
* Create a new user for the database with all permissions on the new database
e.g. for mysql:
grant all privileges on seeddms.* to seeddms@localhost identified by 'secret';
(replace 'secret' with you own password)
* Optionally import `create_tables-innodb.sql` in the new database
e.g. for mysql:
> cat create_tables-innodb.sql | mysql -useeddms -p seeddms
This step can also be done by the install tool.
* create a file `ENABLE_INSTALL_TOOL` in the `conf` directory and point
your browser at http://hostname/seeddms/install
3. Email Notification
---------------------
A notification system allows users to receive an email when a
document or folder is changed. This is an event-based mechanism that
notifies the user as soon as the change has been made and replaces the
cron mechanism originally developed. Any user that has read access to a
document or folder can subscribe to be notified of changes. Users that
have been assigned as reviewers or approvers for a document are
automatically added to the notification system for that document.
A new page has been created for users to assist with the management of
their notification subscriptions. This can be found in the "My Account"
section under "Notification List".
4. Nearly finished
------------------
Now point your browser to http://hostname/seeddms/index.php
and login with "admin" both as username and password.
After having logged in you should first choose "My Account" and
change the Administrator's password and email-address.
CONFIGURING MULTIPLE INSTANCES
==============================
Since version 3.0.0, SeedDMS can be set up to run several parallel instances
sharing the same source but each instance has its own configuration. This is
quite useful if you intend to host SeedDMS for several customers. This
approach still allows to have diffenrent version of SeedDMS installed
and will not force you to upgrade a customer instance, because other
instances are upgraded. A customer instance consists of
1. a directory containing mostly links to the SeedDMS source and a
configuration file
2. a directory containing the document content files
3. a database
1. Unpack the SeedDMS distribution
----------------------------------
Actually there is no need to set up the database at this point but it won't
hurt since you'll need one in the next step anyway. The sources of SeedDMS
can be anywhere you like. The do not have to be in you www-root. If you just
have access to your www-root directory, then put them there.
2. Setup the instance
---------------------
Unpack the files as described in the quick installation.
Create a directory in your www-root or use www-root for your instance. In the
second case, you will not be able to create a second instance, because each
instance needs its own directory.
Go into that directory create the following links (<seeddms-source> is the
directory of your initial SeedDMS intallation).
> src -> <seeddms-source>
> inc -> src/inc
> op -> src/op
> out -> src/out
> js -> src/js
> views -> src/views
> languages -> src/languages
> styles -> src/styles
> themes -> src/themes
> install -> src/install
> index.php -> src/index.php
> ln -s ../seeddms-<version> src
> ln -s src/inc inc
> ln -s src/op op
> ln -s src/out out
> ln -s src/js js
> ln -s src/views views
> ln -s src/languages languages
> ln -s src/styles styles
> ln -s src/themes themes
> ln -s src/install install
> ln -s src/index.php index.php
Create a new directory named conf and run the installation tool.
Creating the links as above has the advantage that you can easily switch
to a new version and go back if it is necessary. You could even run various
instances of SeedDMS using different versions.
3. Create a database and data store for each instance
-----------------------------------------------------
Create a database and data store for each instance and adjust the database
settings in conf/settings.xml or run the installation tool.
Point your web browser towards the index.php file in your new instance.
NOTE FOR VERSION 4.0.0
======================
Since version 4.0.0 of SeedDMS installation has been simplified.
ADOdb is no longer needed because the database access is done by
PDO.
IMPORTANT NOTE ABOUT TRANSLATIONS
=================================
As you can see SeedDMS provides a lot of languages but we are not professional
translators and therefore rely on user contributions.
If your language is not present in the login panel:
- copy the language/English/ folder and rename it appropriately for your
language
- open the file `languages/your_lang/lang.inc` and translate it
- open the help file `languages/your_lang/help.htm` and translate it too
If you see some wrong or not translated messages:
- open the file `languages/your_lang/lang.inc`
- search the wrong messages and translate them
if you have some "error getting text":
- search the string in the english file `languages/english/lang.inc`
- copy to your language file `languages/your_lang/lang.inc`
- translate it
If there is no help in your language:
- Copy the English help `english/help.htm` file to your language folder
- translate it
If you apply any changes to the language files please send them to the
SeedDMS developers <info@seeddms.org>.
http://www.iana.org/assignments/language-subtag-registry has a list of
all language and country codes.
LICENSING
=========
SeedDMS is licensed unter GPLv2
Uwe Steinmann <info@seeddms.org>

View File

@ -1,66 +0,0 @@
Ldap configuration
===================
The configuration for authentication against an ldap server needs to be done
in the `settings.xml` file using a text editor. It cannot be edited from within the
web gui.
SeedDMS supports ldap authentication using an Active Directory (AD) or a
regular ldap server, e.g. openldap
The location of the ldap server is specified in two parameters: `host` and
`port`. `host` can be either a plain hostname or an ldap URI, including the
protocol, the host and optionally the port, e.g. ldap://localhost:389. In case
of an URI the port in the configuration must remain empty.
The authentication itself is a two step process which differs, depending on how
to bind to the server. If the configuration sets 'bindDN' and 'bindPW', those
values will be used for a initial non anonymous bind to the ldap server
otherwise an anonymous bind is executed.
After the initial bind, a ldap search for either 'uid=<username>' (ldap) or
'sAMAccountName=<username>' (AD) below basedn is done. The purpose of this
search is to retrieve a working bindDN which is then used to actually
authenticate the user. In case of an anonymous first bind the search will
likely fail and the bindDN for the second bind will be either
'uid=<username>,<basedn>' (ldap) or '<username>@<accountDomainName>' (AD). If
the search succeeds the bindDN will be taken from the user's data in the ldap
server. This bindDN will be used for a second bind using the users password.
If the second bind succeeds the user could be successfully authenticated.
The data from the ldap server can be used to create an account in SeedDMS
if the user trying to login does not exist yet, but was able to authenticate.
This will only be done if 'authentication->restricted' in the configuration
is set to false. In that case the common name (cn) and email address is taken
from ldap. An already existing account in SeedDMS will be updated with data from
ldap.
Since version 5.1.35 and 6.0.28 the field name of the email address in ldap
can be set with the attribute `mailField`. If it is not set it defaults to `mail`.
Since version 5.1.34 and 6.0.27 the groups of a user stored in the ldap directory
can be synchronised with the groups in SeedDMS. The ldap field storing
the groups can be configured with the attribute `mailField`. This will add
new groups in SeedDMS and aѕsign them to the user.
Examples
---------
Anonymous bind to openldap on localhost, port 389
- type = "ldap"
- baseDN = "ou=users,dc=mycompany,dc=de"
- host = "ldap://localhost"
During authentication as user 'admin' the following steps are executed
1. connect to ldap server at localhost:389
2. do an anonymous bind
3. search for 'uid=admin' below basedn
4.1. if search succeeds use the dn from the user
4.2. if search fails use 'uid=admin,<basedn>' as dn
5. do a non anonymous bind with dn and password entered by user
6. if step 5. succeeds the use is authenticated
If bindDN and bindPW are specified in the configuration, the second step
will be a non anonymous bind.

View File

@ -1,29 +0,0 @@
Mail configuration
===================
SeedDMS uses email to
* notify users about changes of documents and folders
* send instructions during the password forgotten process
Configuring email in SeedDMS is simple on systems running a
local mail server, because this is the default in SeedDMS and
no additional configuration is needed. On Linux you should
consider running a local mail server, which relais the mails
to your outgoing mail server. If you cannot run a local mail
server, you can still configure SeedDMS to use an outgoing
SMTP server. Below are some examples on how to configure
SeedDMS for different hosters.
1&1
---------
smtp server: ssl://smtp.1und1.de
smtp port: 465
Gmail
---------
smtp server: ssl://smtp.gmail.com
smtp port: 465
note: since June, 2022 you will no longer be able to turn on 'Less secure app access' in your google account. Instead you need to turn on 2-Step Verification first and than
create an App Password (https://support.google.com/accounts/answer/185833)

View File

@ -1,55 +0,0 @@
# How to access the Rest API
Below are various examples on how to access the Rest API. Some of them
start by calling the `login` endpoint which creates a cookie based
session which is stored in a local file named `cookies.txt`.
The authentication is done with the user `admin`. You may use any other
user as well.
You may as well pass `-H Authorization: <api key>` instead of `-b cookies.txt`
to `curl` after setting the api key in the configuration of your SeedDMS.
Of course, in that case you will not need the initial call of the `login`
endpoint.
The examples often use the `jq` programm for formating the returned
json data.
## Initial test
The `echo` endpoint does not require any authentication.
```
#!/bin/sh
BASEURL="https://your-domain/"
curl --silent -X GET ${BASEURL}restapi/index.php/echo/test | jq '.'
```
## Getting list of users
```
#!/bin/sh
BASEURL="https://your-domain/"
curl --silent -F "user=admin" -F "pass=admin" -b cookies.txt -c cookies.txt ${BASEURL}restapi/index.php/login | jq
curl --silent -b cookies.txt -X GET "${BASEURL}restapi/index.php/users" | jq '.'
```
## Getting meta data of a folder
```
#!/bin/sh
BASEURL="https://your-domain/"
curl --silent -H "Authorization: <api key>" -X GET "${BASEURL}restapi/index.php/folder/1" | jq '.'
```
## Notes
Make sure to encode the data properly when using restapi functions which uses
put. If you use curl with PHP, then encode the data as the following
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));

View File

@ -1,39 +0,0 @@
Review/Approval
------------------
The traditional Review/Approval process has been around for a long time
already and is still available, though the new workflow engine has been
introduced.
Review/Approval is a very simple, but in many cases sufficient, workflow
to review and approve document versions. Review and approval is done by users
in behalf of themself or the group they belong to. A document version
is reviewed or approved if all users and groups in charge of it, have
found the document version to be ready and worth for release. If a single
user rejects it, it will not change its status to 'released' but to 'rejected'.
Review is always done before approval, but a document version may not have
to run through both processes.
A version can use just the approval process without a review before,
and it can also skip the approval process and just run through review. In
the second case the document will be released immidiately after successful
review.
If a group is in charge for reviewing/approving a document, it will be
sufficient if one member of that group takes action.
Internally SeedDMS keeps a record of all approval/review actions done on
a document version. When a document version is uploaded with both processes
in place, then for each user/group a list of log entries is created. Any
action on the document will add a new entry to the log. Those entries
contain the action (release/reject), a user comment and the current date.
Each entry will also trigger an internal function which checks, whether
the last action causes a document state change. Such a state change happens
when all reviews or approvals are done, or if a review/approval is rejected.
If a user or a group is deleted and some documents are still waiting for
a review/approval, this will also be logged and the review/approval will
no longer be needed to release the document.
Before a document leaves the approval or review state any review/approval
or reject can be changed. So if a user initially approves a document and
later changes her/his mind, he/she can still reject the document.

View File

@ -1,26 +0,0 @@
Scheduler
==========
The scheduler in SeedDMS manages frequently run tasks. It is very similar
to regular unix cron jobs. A task in SeedDMS is an instanciation of a task
class which itself is defined by an extension or SeedDMS itself.
SeedDMS has some predefined classes e.g. core::expireddocs.
In order for tasks to be runnalbe, a user `cli_scheduler` must exists in
SeedDMS.
All tasks are executed by a single cronjob in the directory `utils`
> */5 * * * * /home/www-data/seeddms60x/seeddms/utils/seeddms-schedulercli --mode=run
Please keep in mind, that the php interpreter used for the cronjob may be
different from the php interpreter used für the web application. Hence, two
different php.ini files might be used. php and the php extensions may differ as
well. This can cause some extensions to be disabled and consequently some task
classes are not defined.
`utils/seeddms-schedulercli` can also be run on the command line. If you
do that, run it with the same system user used for the web server. On Debian
this is www-data. Hence run it like
sudo -u www-data utils/seeddms-schedulercli --mode=list

View File

@ -1,23 +0,0 @@
Swagger
========
Swagger is used to describe a rest api. SeedDMS ships a swagger.yaml file
in the restapi directory. You can load this file into a swagger editor, e.g.
http://petstore.swagger.io/ or http://editor.swagger.io/
You may as well set up your own swagger-ui installation as described at
https://medium.com/@tatianaensslin/how-to-add-swagger-ui-to-php-server-code-f1610c01dc03
Your apache needs to have the module `header` enabled, because some HTTP headers
are set when the file `swagger.yaml` is accessed by the editor.
Currently, the swagger.yaml shipped with SeedDMS uses still swagger 2.0
If you are using php-fpm you will have to ensure that files with
extension .yaml are allowed to be parsed. Extend the
`security.limit_extensions` in the pool configuration by `.yaml`. Also
check the contents of the file `.htaccess` in directory `restapi`. It
by default sets the handler for php to `application/x-httpd-php` which
uses the apache module of php. If you would like to use php-fpm
instead, then set it to
SetHandler "proxy:unix:/var/run/php/php8.2-fpm.sock|fcgi://localhost/"

View File

@ -1,163 +0,0 @@
*********************************************
How to set up a Synology NAS to run SeedDMS
*********************************************
**This guide has been updated and tested to work on Synology DSM 6.0. It should as well work with older DMS versions, however some steps or paths may be different.**
Introduction
############
SeedDMS is a feature rich and lightweight document management system. Unfortunately, some of the tools which are part of many Linux distros, have not been made available by
Synology and therefore require additional steps to bring them to your Synology.
This guide covers the installation of the required tools to have all features of SeedDMS available. It does not cover the installation of 3rd party programs (like OPKG). It
does not cover the installation of SeedDMS as well, please refer to the separate README.Install.md file.
Prerequisites
#############
In order to complete the steps outlined below, you must be able to carry out the following tasks:
* Use the command line and know essential commands
* Install a 3rd party package system and install packages using this system
To complete the installation, the following prerequisites on your Synology must be met:
* IPKG or OPKG (OPKG preferred) installed
* PEAR installed from the Synology Package Center
Installation and configuration
##############################
In the following steps, you will first install the required packages, followed by doing the neccesary configurations. These steps
must be done on the terminal.
Install Ghostscript
***************************
The first step is to install Ghostscript to make ImageMagick capable of converting PDF files to images which are then used for previews.
Use IPKG or OPKG to complete this step.
Make Ghostscript available to PHP
*****************************************
To check where Ghostscript is installed run *which gs* to get the installation path. Now check if this path is visible to PHP. To check this,
use phpinfo and find **_SERVER["PATH"]**. If you can't find /opt inside, PHP can't see applications installed there. You can now either try to
update the paths or just make a symlink.
To create the symlink, cd to /usr/bin and type *ln -s /opt/bin/gs gs*. Verify the created symlink.
Fix ImageMagick
********************
Not only Ghostscript is affected by bugs, the default configuration files for ImageMagick are missing. Unfortunately some work is required here as well.
To check where ImageMagick looks for it's files, invoke the command *convert -debug configure logo: null:*. You will see some paths shown, these
are the paths where ImageMagic tries to locate it's configuration files. The first path shown will point to */usr/share/ImageMagick-6* followed by the
name of an XML file. At the very end of the output you will see which configuration file has been loaded, in the default setting there will be an error.
Point to */usr/share* and check if you can find the **ImageMagick-6** directory. If is not present, create it. Cd into the directory.
Next step is to fill the directory with files. Use the following list to download the files (credit goes to Thibault, http://blog.taillandier.name/2010/08/04/mediawiki-sur-son-nas-synology/).
* wget http://www.imagemagick.org/source/coder.xml
* wget http://www.imagemagick.org/source/colors.xml
* wget http://www.imagemagick.org/source/configure.xml
* wget http://www.imagemagick.org/source/delegates.xml
* wget http://www.imagemagick.org/source/english.xml
* wget http://www.imagemagick.org/source/francais.xml
* wget http://www.imagemagick.org/source/locale.xml
* wget http://www.imagemagick.org/source/log.xml
* wget http://www.imagemagick.org/source/magic.xml
* wget http://www.imagemagick.org/source/mime.xml
* wget http://www.imagemagick.org/source/policy.xml
* wget http://www.imagemagick.org/source/thresholds.xml
* wget http://www.imagemagick.org/source/type-ghostscript.xml
* wget http://www.imagemagick.org/source/type-windows.xml
* wget http://www.imagemagick.org/source/type.xml
Testing
*************
Now you should be ready to test. Put a PDF file in a directory, cd into this directory.
To test convert directly, invoke the following command (replace file.pdf with your filename, replace output.png with your desired name):
**convert file.pdf output.png**
If everything goes well you should now receive a png file which can be opened. There may be a warning message about iCCP which can be ignored.
If you want to test Ghostcript as well, invoke the follwing command:
**gs -sDEVICE=pngalpha -sOutputFile=output.png -r144 file.pdf**
This command should go through without any errors and as well output a png file.
If the tests above are successful, you are ready to use SeedDMS Preview.
Install PEAR packages
*********************
This step is similar to the installation on other Linux distros. Once you installed PEAR from the Package Center you can call it from the command line.
The following packages are required by SeedDMS:
* Auth_SASL
* HTTP_WebDAV_Server
* Log
* Mail
* Net_SMTP
Install these packages, then go to the next step.
Install additional packages
***************************
SeedDMS uses other small tools (for example the Slim Framework) to add some additional functionality. At the moment (Version 5.0.x) the list contains the following
tools:
* FeedWriter
* Slim
* parsedown
Copy the tools to a folder on your Synology. Using the console, copy the tools to **/volume1/@appstore/PEAR**.
Copy the whole folders as they are and do not change the structure. As the PEAR directory is already within
the PHP include path, no further configuration is required to get them working.
Fulltext Index
***************
If you do not intend to use the fulltext index, please skip this section and continue with the readme file to
install SeedDMS.
To create the fulltext index, SeedDMS needs to be able to convert the documents to text files to read the terms
out. Pdftotext is already available by default, so we just need to take care of the Microsoft Office formats.
For this guide, the following two tools have been selected:
docx2txt available from http://docx2txt.sourceforge.net/
xlsx2csv available from http://github.com/dilshod/xlsx2csv
Copy both files to your Synology.
**docx2txt**
This program runs without any kind of installation. Create a folder on your Synology and extract the contents of the archive.
In SeedDMS you can now configure the setting for Word documents to the path where you extracted the files in the step before. Point
to the docx2txt.sh file and you are done.
To make the configuration more simple you can add a symlink in **/usr/bin**. This will allow you to call docx2txt from any location of your Synology.
The symlink must point to docx2txt.sh to get it working. In SeedDMS you can now just configure docx2txt followed by any additional commands.
**xlsx2csv**
This one must be installed to get it working. The installation script is written in Python, so you need to get Python installed on your Synology.
As the version available from Synology does not properly work (you can't install PIP) it is strongly recommended to use OPKG or IPKG to install Python.
Install Python and PIP. Once completed, point to the directory where you copied xlsx2csv. Unpack the archive, then execute the installer (pip install xlsx2csv).
Once completed, xlsx2csv is available and can be configured within SeedDMS.
Complete the installation
*************************
Now you are ready to install SeedDMS and configure the database. Follow the README file to install SeedDMS.

View File

@ -1,42 +0,0 @@
Help translating SeedDMS
===========================
SeedDMS has got many translations over the years and it is a major
task to keep them all updated. If you would like to give a helping
hand, then this will be much appreciated. There are various ways
to contribute translations.
1. The demo version of SeedDMS at https://demo.seeddms.org will list
all missing translations in a formular on the bottom of the page
while using the software. You can easily provide a missing translation
by filling out the form and submitting it. The translation will not
instantly be used, but is taken over into the official version of
SeedDMS once in a while. This method does not allow to submit corrected
translations of existing phrases.
2. Fixing translations is only possible by modifying one of the language
files in `lanuages/xx_XX/lang.inc`. These files are php files containing
one large array named `$text`. Any modification will be visible right away
in your SeedDMS installation. If you intend to pass your modifications to
the developers of SeedDMS, than keep your changes seperate from the
original translation. A good way is to put your changes into a new
file, e.g. `lang-local.inc` containing an array named `$text_local` and
merge that array with the original translation array. Just put at the
end of `lanuages/xx_XX/lang.inc` the follwing code:
include('lang-local.inc');
array_merge($text, $text_local);
Also create the file `lang-local.inc` with the content
<?php
$text_local = array(
'xxx' => 'yyy',
);
?>
Once you are ready with your local modifications and you think those are
good enough for the public version of SeedDMS, then please mail them to
info@seeddms.org

View File

@ -1,133 +0,0 @@
WebDAV
========
SeedDMS has support for WebDAV which allows to easily add, delete,
move, copy and modify documents. All operating systems have support
for WebDAV as well, but the implemtations and their behaviour varys
and consequently you may run into various problems. If this happens
just file a bug report at https://sourceforge.net/projects/seeddms
The folder structure in SeedDMS is similar to a regular file system
but it is not identical. SeedDMS distinguishes between a document
and its content, while a file system knows just files.
In SeedDMS a document is uniquely identified
by its document id and not neccessarily by its name. A filesystem
requires a unique paths for each file. Two identical files in the
same folder are not possible. SeedDMS can handle identically named
documents in one folder. In order to prevent any problems arising from
this, you should always disallow identical document names in the
settings. By definition a file in WebDAV is mapped on the latest
version of a document in SeedDMS. There is no way to access previous
versions of a document via WebDAV. Whenever you modify a file and
upload it with the web gui,
a new version will be created. Unfortunately, this has some very
nasty side effects when you edit a document version via WebDAV and
often save it, because any save
operation will create a new version. This is why the WebDAV
server has a configuration option which allows to either replace
the content of document or creating a new
version if a document is saved.
Configuring davfs2
-------------------
On Linux it is quite simple to mount the SeedDMS WebDAV server with
davfs2. Just place a line like the following in your /etc/fstab
http://seeddms.your-domain.com/webdav/index.php /media/webdav davfs noauto,user,rw,uid=1000,gid=1000
and mount it as root with
mount /media/webdav davfs
You may as well want to configure davfs2 in /etc/davfs2/davfs2.conf by setting
[/media/webdav]
use_locks 0
gui_optimize 1
and possibly add your login data to /etc/davfs2/secrets
/media/webdav admin secret
Making applications work with WebDAV
-------------------------------------
Various programms have differnt strategies to save files to disc and
prevent data lost under all circumstances. Those strategies often don't
work very well an a WebDAV-Server. The following will list some of those
strategies.
### VIM
vim does a lot more than just reading and writing the file you want
to edit. It creates swap and backup files for data recovery if vim crashes
or is being killed unexpectively. On a low bandwidth connection this can
slow down the editing. For that reason you should either not create the
swap file at all or create it outside the WebDAV server. A second problem
arises from how vim modifіes the file you are editing. Before a file
is saved a backup is created by renaming the file to the same name with a
'~' at the end and writing the file content into a new
file with the name of the original file. Afterwards vim deletes the backup
file. On a regular file system you
won't see a difference between the file before and after saving, though
it is actually a new one. In SeedDMS you won't notice a difference either
by just looking at the document name. It's still the same, but the
document id has changed. So saving a document will delete the
old document and create a new one instead of creating a new version of
the old document. If you don't want this behaviour, then tell vim
to not create the backup file. You can do that by either passing additional
parameters to vim
vi "+set nobackup" "+set nowritebackup" -n test.txt
or by setting them in your .vimrc
set nobackup
set nowritebackup
set noswapfile
If you want to restrict the settings to the directory where the dms
is mounted by webdav, e.g. /media/webdav, you can set an auto command
in .vimrc
autocmd BufNewFile,BufRead /media/webdav/* set nobackup nowritebackup noswapfile
Creating the backup file in a directory outside of WebDAV doesn't help in
this case, because it still does the file renaming which is turned off by
'nowritebackup'.
### cdaver
cadaver is a webdav client similar to classical command line based ftp clients.
It can be used to browse through the folders, downloads and uploads files, and
also for removing and moving folders and documents (called resources in webdav terminilogy).
It's also capable of setting and getting properties of folders and documents.
If webdav access isn't working, this client is probably the best for testing.
Just run
cadaver https://<your-domain>/<your-basedir>/webdav/index.php
It will ask for the user name and password. Once you are logged in just
type `help` for a list of commands.
SeedDMS stores a lot more properties not covered by the webdav standard.
Those have its own namespace called 'SeedDMS:'. Just type
propget <resource>
with `resource` being either the name of a folder or document. You will
get a list of all properties stored for this resource. Setting a property
requires to set the namespace first
set namespace SeedDMS:
Afterwards, you may set a property, e.g. the comment, with
propset <resource> comment 'Just a comment'
or even delete a property
propdel <resource> comment

View File

@ -1,42 +0,0 @@
Running the scheduler
======================
Since version 6 of SeedDMS a scheduler is implemented which runs
scheduled tasks. Such tasks must be implemented in an extension
and can be scheduled by the administrator within the user interface.
In order to check frequently for tasks ready to run, a system cron job
must be installed. On Linux this can be done by adding the following line
to the crontab
*/5 * * * * /var/www/seeddms60x/seeddms/utils/seeddms-schedulercli --mode=run
(Of course you need to change the path to `seeddms-schedulercli`)
This will install a cronjob running every 5 minutes. `seeddms-schedulercli` will check
for tasks ready to run and execute them in that case. You can decrease the time between
two calls of the cronjob, but keep in mind that seeddms tasks may take longer and
are being started again before the previous task has been ended.
If the configuration file of SeedDMS is not found, its path can be passed
on the command, though this should not be needed in a regular installation
obeying the directory structure of the quickstart archive.
*/5 * * * * /var/www/seeddms60x/seeddms/utils/seeddms-schedulercli --config /var/www/seeddms60x/seeddms/conf/settings.xml --mode=run
For testing purposes it may be usefull to run `seeddms-schedulercli` in list mode.
seeddms-schedulercli --mode=list
This will just list all tasks and its scheduled exection time. Tasks ready to run,
because its scheduled execution time is already in the past will be marked with
a `*`. Tasks which are disabled will be marked with a `-`.
Executing `seeddms-schedulercli` in `dryrun` mode will behave just like in `run` mode
but instead of running the task it will just issue a line.
Instead of running utils/seeddms-schedulercli you may as well access
op/op.Cron.php which also runs all scheduled tasks. On Linux you do this
by setting up a cronjob like
*/5 * * * * wget -q -O - "http://<your domain>/op/op.Cron.php"

View File

@ -1,16 +0,0 @@
Installation of external js packages
-------------------------------------
All javascript was located in styles/bootstrap until SeedDMS 5.1.18 and 6.0.11.
Since 5.1.19 and 6.0.12 most of it has moved into the view at views/boostrap/vendors
and is no longer placed in git but must be installed by npm and grunt.
Run
`npm install`
and afterwards
`grunt`
to download the js packages and copy them into the new location.

View File

@ -1,59 +0,0 @@
OCR
====
SeedDMS itself has no support for optical character recognition (OCR)
because it does not care about the content of file. Though, external
OCR software can be used to convert an image into text and index it
by the full text search engine.
The following script can be use to convert a scanned image into pdf
with a text layer added. The script actually takes this file to
ran it through pdftotext. It was published in the seeddms forum
https://sourceforge.net/p/seeddms/discussion/general/thread/4ec5973d/
#!/bin/bash
inputpdf=$1
temp_folder=/tmp/seedinput/$(date +"%Y_%m_%d_%H%M%S")/
lockfile=/tmp/seed
protokolldatei=./tesser_syslog
cores=2
mkdir -p $lockfile
while [ -e "$lockfile"/"`basename $0`" ];
do
sleep 5
done
if ( set -o noclobber; echo "locked" > "$lockfile"/"`basename $0`"); then
trap 'rm -f "$lockfile"/"`basename $0`"; echo $(date) " Lockdatei wird geloescht: " $lockfile"/"`basename $0` Aufrufparameter: $* >> $protokolldatei ;rm -r $temp_folder; exit $?' INT TERM KILL EXIT
#das Datum mit dem Scriptnamen in die Protokolldatei schreiben
echo $(date) " Lockdatei erstellt: " $lockfile"/"`basename $0` >> $protokolldatei
else
#Script beenden falls Lockdatei nicht erstellt werden konnte
echo $(date) " Programm wird beendet, Lockdatei konnte nicht erstellt werden: $lockfile"/"`basename $0` Aufrufparameter: $* " >> $protokolldatei
exit 1
fi
mkdir -p $temp_folder
$(pdftotext -raw $1 - 1> $temp_folder''tmp.txt )
pdf_contents=`cat $temp_folder''tmp.txt`
pdf_contents=`echo "$pdf_contents" | tr -dc '[:print:]'`
if [ -z "$pdf_contents" ]; then
convert -density 300 -quality 95 $inputpdf +adjoin $temp_folder''image%03d.jpg
find $temp_folder -name '*.jpg'| parallel --gnu -j $cores tesseract -l deu --psm 6 {} {} pdf
num=`find $temp_folder -name '*.pdf'| wc -l`
if [ "$num" -gt "1" ]; then
pdfunite $temp_folder*.pdf $temp_folder''tmp.pdf
else
mv $temp_folder*.pdf $temp_folder''tmp.pdf
fi
pdftotext $temp_folder''tmp.pdf $temp_folder''tmp.txt
mv $temp_folder''tmp.pdf $1
fi
cat $temp_folder''tmp.txt

View File

@ -1,36 +0,0 @@
Howto configure mod_xsendfile
==============================
Downloading large files from SeedDMS can be slow, because they are delivered
by the PHP download script. This is a common problem not specific to SeedDMS
but to PHP scripts of this kind in general. Granting direct access on the
download file is not a option as it circumvents the access restrictions of
SeedDMS.
The Apache module xsendfile is just for this kind of controlled downloads. If
is installed and configured, SeedDMS will hand over the download to the web
server which does a much better job than the PHP script. In order to make it
work, mod_xsendfile must be installed, turned on and the path to the download
files must be set to the directory containing the document files. If your document
root is /var/www and you extracted the quickstart archive into that directory,
then the document content directory will be at
/var/www/seeddms51x/data/ . Add the following to your apache configuration,
either globally or within a virtual host configuration. Setting the path in
an .htaccess file will not work.
XSendFile on
XSendFilePath /var/www/seeddms51x/data/
If the XSendFilePath is not set propperly, you will notice an error message
in your apache log file, probably telling you that the download file could not
be found.
A positive side effect of xsendfile is support for content ranges which are
currently *not* supported by seeddms' Download and ViewOnline scripts. This is
especially usefull when previewing videos. Without content ranges it is not
possible to jump to certain time in the video.
In order to check if the xsendfile module is loaded, php uses apache_get_modules()
which is only available if php is loaded as an apache module. Running php in fpm
mode will prevent php from checking for xsendfile and consequently xsendfile support
will not be available.

View File

@ -1,9 +0,0 @@
Changes in version 1.0.1
==========================
- added this changelog file
Changes in version 1.0.0
==========================
- Initial version

View File

@ -1,208 +0,0 @@
<?php
/***************************************************************
* Copyright notice
*
* (c) 2013 Uwe Steinmann <uwe@steinmann.cx>
* All rights reserved
*
* This script is part of the SeedDMS project. The SeedDMS project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script 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.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
* Example extension
*
* @author Uwe Steinmann <uwe@steinmann.cx>
* @package SeedDMS
* @subpackage example
*/
class SeedDMS_ExtExample extends SeedDMS_ExtBase {
/**
* Initialization
*
* Use this method to do some initialization like setting up the hooks
* You have access to the following global variables:
* $this->settings : current global configuration
* $this->settings->_extensions['example'] : configuration of this extension
* $GLOBALS['LANG'] : the language array with translations for all languages
* $GLOBALS['SEEDDMS_HOOKS'] : all hooks added so far
*/
function init() { /* {{{ */
$GLOBALS['SEEDDMS_HOOKS']['initDMS'][] = new SeedDMS_ExtExample_InitDMS;
$GLOBALS['SEEDDMS_HOOKS']['view']['addDocument'][] = new SeedDMS_ExtExample_AddDocument;
$GLOBALS['SEEDDMS_HOOKS']['view']['viewFolder'][] = new SeedDMS_ExtExample_ViewFolder;
$GLOBALS['SEEDDMS_SCHEDULER']['tasks']['example']['example'] = new SeedDMS_ExtExample_Task;
} /* }}} */
function main() { /* {{{ */
} /* }}} */
}
class SeedDMS_ExtExample_HomeController { /* {{{ */
protected $dms;
protected $settings;
public function __construct($dms, $settings) {
$this->dms = $dms;
$this->settings = $settings;
}
public function home($request, $response, $args) {
$response->getBody()->write('Output of route /ext/example/home'.get_class($this->dms));
return $response;
}
public function echos($request, $response, $args) {
$response->getBody()->write('Output of route /ext/example/echo');
return $response;
}
} /* }}} */
/**
* Class containing methods for hooks when the dms is initialized
*
* @author Uwe Steinmann <uwe@steinmann.cx>
* @package SeedDMS
* @subpackage example
*/
class SeedDMS_ExtExample_InitDMS { /* {{{ */
/**
* Hook after initializing the application
*
* This method sets the callback 'onAttributeValidate' in SeedDMS_Core
*/
public function addRoute($arr) { /* {{{ */
$dms = $arr['dms'];
$settings = $arr['settings'];
$app = $arr['app'];
$container = $app->getContainer();
$container['HomeController'] = function($c) use ($dms, $settings) {
// $view = $c->get("view"); // retrieve the 'view' from the container
return new SeedDMS_ExtExample_HomeController($dms, $settings);
};
$app->get('/ext/example/home', 'HomeController:home');
$app->get('/ext/example/echos',
function ($request, $response) use ($app) {
echo "Output of route /ext/example/echo";
}
);
return null;
} /* }}} */
} /* }}} */
/**
* Class containing methods for hooks when a document is added
*
* @author Uwe Steinmann <uwe@steinmann.cx>
* @package SeedDMS
* @subpackage example
*/
class SeedDMS_ExtExample_AddDocument {
/**
* Hook before adding a new document
*/
function preAddDocument($view) { /* {{{ */
} /* }}} */
/**
* Hook after successfully adding a new document
*/
function postAddDocument($view) { /* {{{ */
} /* }}} */
}
/**
* Class containing methods for hooks when a folder view is ѕhown
*
* @author Uwe Steinmann <uwe@steinmann.cx>
* @package SeedDMS
* @subpackage example
*/
class SeedDMS_ExtExample_ViewFolder {
/**
* Hook when showing a folder
*
* The returned string will be output after the object menu and before
* the actual content on the page
*
* @param object $view the current view object
* @return string content to be output
*/
function preContent($view) { /* {{{ */
return $view->infoMsg("Content created by viewFolder::preContent hook.");
} /* }}} */
/**
* Hook when showing a folder
*
* The returned string will be output at the end of the content area
*
* @param object $view the current view object
* @return string content to be output
*/
function postContent($view) { /* {{{ */
return $view->infoMsg("Content created by viewFolder::postContent hook");
} /* }}} */
}
/**
* Class containing methods for running a scheduled task
*
* @author Uwe Steinmann <uwe@steinmann.cx>
* @package SeedDMS
* @subpackage example
*/
class SeedDMS_ExtExample_Task extends SeedDMS_SchedulerTaskBase {
/**
* Run the task
*
* @param $task task to be executed
* @return boolean true if task was executed succesfully, otherwise false
*/
public function execute($task) {
$dms = $this->dms;
$user = $this->user;
$settings = $this->settings;
$logger = $this->logger;
$taskparams = $task->getParameter();
return true;
}
public function getDescription() {
return 'Description';
}
public function getAdditionalParams() {
return array(array(
'name'=>'email',
'type'=>'string',
'description'=> '',
));
}
}

Some files were not shown because too many files have changed in this diff Show More