,
Request #5936).
--------
v2.2-RC1
--------
[jan] Implement WebDAV DELETE.
[cjh] Add quick links to the sidebar block for adding notes to a specific
notepad (Gunnar Wrobel , Request #5716).
[cjh] Fix generation of UIDs with PHP 5.2+.
----------
v2.2-ALPHA
----------
[cjh] Show tooltips in the summary block, and restrict tooltips to 20 lines
(Request #3443).
[cjh] Optionally show a note's notepad in the list view (Request #2317).
[cjh] Add quick (inline) note searching.
[cjh] Add the ability to save a note as a PDF.
[jan] Add support for encrypted notes.
[cjh] Move notepad selection/deselection to a collapsible panel.
[mas] Conform to WCAG 1.0 Priority 2/Section 508 accessibility guidelines.
(Request #4080)
[cjh] Notes search should be either title or full text (Request #4277).
[cjh] Make the note edit view the full page width.
------
v2.1.2
------
[jan] SECURITY: Fix privilege escalation in Horde API.
[cjh] SECURITY: Fix missing ownership validation on share changes.
------
v2.1.1
------
[jan] Show error message if imported file didn't contain notes.
[jan] Add Slovenian translation (Duck ).
[jan] Add categories from imported contacts to the user's categories.
[jan] Show personal notepad by default with disabled preferences (Bug #4078).
----
v2.1
----
[jan] Fix portal block if used with Kolab driver (tokoe@kde.org, Bug #2735).
[jan] Add Russian translation (Alexey Zakharov ).
[ben] Better support for MS-SQL.
--------
v2.1-RC1
--------
[jan] Confirm note deletions (Request #1156).
[jan] Add CLI script to import vNote data.
[cjh] Add support for dynamic re-sorting of the note list, including saving
the sort preferences on any changes.
[jan] Show character count next to notes.
[mas] Change any output of and tags to and for better
accessibility support.
[jan] Add permissions to restrict number of notes.
------
v2.0.3
------
[cjh] Close several XSS vulnerabilities with note and notepad data.
------
v2.0.2
------
[jan] Allow to import more than one note from vNote data at once.
----------
v2.0.2-RC1
----------
[cjh] Fix resetting categories to Unfiled (Bug #2018).
[cjh] Use bind variables in SQL driver, clean up required parameters
(selsky@columbia.edu, Bug #1791).
[cjh] Add a PostgreSQL upgrade script (Bug #1779).
[cjh] Better error handling when deleting shares that don't exist (Bug #1754).
[jan] Add Japanese translation (Hiromi Kimura ).
[jan] Add shortcut icon (favicon.ico).
------
v2.0.1
------
[jan] Fix print view.
[jan] Fix print button.
----
v2.0
----
[cjh] UIDs need to be stored in the History system with a mnemo: prefix and
with the notepad so as not to confuse different instances of the
same note (if two users both have a note on their seperate notepads,
they should have unique histories for that note).
[cjh] Don't throw a fatal error if an empty share name is submitted
(Bug #1000).
--------
v2.0-RC3
--------
[cjh] Add My Notepads menu entry.
--------
v2.0-RC2
--------
[jan] Add Czech translation (Pavel Chytil ).
[jan] Add Latvian translation (Janis Eisaks ).
--------
v2.0-RC1
--------
[jan] Tweak layout of the summary block.
---------
v2.0-BETA
---------
[jan] Add Polish translation (Mateusz Kaminski ).
[jan] Add special black-on-white styles for message printing.
[jan] Add access keys.
[cjh] Add Kolab drivers (Stuart Bingë ).
----------
v2.0-ALPHA
----------
[cjh] GUIDs now only contain mnemo: and the note ID - sharename is not needed.
[cjh] Note IDs are now 32-character unique strings, to be useable as GUIDs.
The SQL table definition has changed; conversion scripts are in scripts/.
[cjh] The notes/ API now implements the modern methods required for SyncML and
other syncing efforts.
[cjh] Make sure there is a view link for empty notes.
[cjh] Add a Delete link from the note edit screen.
[cjh] Make sure that the correct categories for a note's current notepad
are always used.
[cjh] Change how memos are stored in the SQL driver.
scripts/create_sequence.php will update an existing database with no
loss of data.
[cjh] Display the Creation and Last-Modified dates in the note view.
[cjh] Track addition, modification, and deletion of notes
with the Horde History:: API.
[cjh] Add import of vNotes.
[cjh] Show the full memo body in a tooltip.
[cjh] Add a preference for the default category for notes
(Brian Keifer ).
[jan] Add UTF-8 support and charset parameter for backend drivers.
[jan] Only show selected note categories on the summary screen
(Brian Keifer ).
[cjh] Much more comprehensive permissions checking, and support for
guest access.
[cjh] Use the global shares editing page for changing/assigning share
permissions.
[mac] Allow importing onto any available Notepad.
[mac] Add shared notepads.
------
v1.1.4
------
[jan] Close XSS when setting the parent frame's page title by javascript (cjh).
------
v1.1.3
------
[jan] Add Polish translation (Mateusz Kaminski ).
------
v1.1.2
------
[jan] Make memos without description accessible from the memo list.
------
v1.1.1
------
[jan] Add Italian translation (Sergio G. Caredda ).
[jan] Add Romanian translation (Eugen Hoanca ,
Marius Dragulescu ).
----
v1.1
----
[jan] Rename Memos to Notes (mac).
[jan] Add print memo button (mac).
[jan] Show current category color in category color options screen
(Jan Kuipers ).
[jan] Add ability to create/remove categories (mac).
[jan] Add user preferences for the color of different categories (mac).
[jan] Add Mnemo::addParameter().
[jan] Add Greek translation (Stefanos I. Dimitriou ).
[jan] Add Slovak translation (Ivan Noris ).
[jan] Add Norwegian Bokmaal translation (Torstein S. Hansen ).
[jan] Add Bulgarian translation (Miroslav Pendev ).
[jan] Add Lithuanian translation (Darius Matuliauskas ).
[jan] Replace = with ).
----
v1.0
----
[jan] Add Hungarian translation (Laszlo L. Tornoci ).
[jan] Add Simplified Chinese translation (Peter Wang ).
[jan] Add Czech translation (Pavel Chytil ).
[jan] Add Brazilian Portuguese translation (Antonio Dias ).
[jan] Add Dutch translation (Jan Kuipers ).
[jan] Add French translation (Thierry Thomas ).
[jan] Add Finnish translation (Leena Heino ).
[jan] Add Norwegian Nynorsk translation (Per-Stian Vatne ).
[jan] Add Traditional Chinese translation (Chih-Wei Yeh ).
[jan] Add Swedish translation (Andreas Dahlén ).
[jan] Add Spanish translation (Raul Alvarez Venegas ).
[jan] Add German translation.
[jan] Add Portuguese translation (Nuno Loureiro ).
[cjh] Initial Mnemo version, based on Nag.
mnemo-4.2.9/docs/CREDITS 0000664 0001750 0001750 00000011172 12654116457 012732 0 ustar jan jan ========================
Mnemo Development Team
========================
Core Developers
===============
- Chuck Hagenbuch
- Jan Schneider
Localization
============
===================== ======================================================
Basque Euskal Herriko Unibertsitatea
Brazilian Portuguese Antonio Dias
Fabio Gomes
Luis Felipe Marzagao
Eduardo de Carli
Bulgarian Miroslav Pendev
Chinese (Simplified) Peter Wang
Anna Chen
Chinese (Traditional) Chih-Wei Yeh
Croatian Matej Vela
Czech Pavel Chytil
Michael Grafnetter
Danish Martin List-Petersen
Brian Truelsen
Niels Baggesen
Erling Preben Hansen
Dutch Jan Kuipers
Finnish Leena Heino
French Thierry Thomas
Patrick Abiven
Vincent Vinet
Yannick Sebastia
Laurent Foucher
Paul De Vlieger
German Jan Schneider
Greek Stefanos I. Dimitriou
Silligardos Xristoforos
Anagnostopoulos Apostolis
Konstantinos C. Milosis
Hungarian Laszlo L. Tornoci
Andras Galos
Zoltán Németh
Italian Sergio G. Caredda
Marko Djukic
Marco Pirovano
Cristian Manoni
Massimo Malabotta
Massimo Balestrieri
Japanese Hiromi Kimura
Korean Deokgon Kim
Josh Kim
Latvian Janis Eisaks
Lithuanian Darius Matuliauskas
Vilius Šumskas
Norwegian Bokmaal Torstein S. Hansen
Norwegian Nynorsk Per-Stian Vatne
Polish Mateusz Kaminski
Piotr Tarnowski
Krzysztof Kozera
Maciej Uhlig
Portuguese Nuno Loureiro
Manuel Menezes de Sequeira
Romanian Eugen Hoanca
Marius Dragulescu
Russian Alexey Zakharov
Slovak Ivan Noris
Martin Matuška
Jozef Sudolský
Slovenian Duck
Spanish Raul Alvarez Venegas
Manuel Perez Ayala
Juan C. Blanco
Swedish Andreas Dahlén
Joaquim Homrighausen
Per Olof Ljungmark
Turkish Istanbul Technical University IT Department
Middle East Technical University
Ukrainian Andriy Kopystyansky
===================== ======================================================
mnemo-4.2.9/docs/INSTALL 0000664 0001750 0001750 00000013170 12654116457 012743 0 ustar jan jan =====================
Installing Mnemo H5
=====================
This document contains instructions for installing the Mnemo web-based notes
application on your system.
For information on the capabilities and features of Mnemo, see the file
README_ in the top-level directory of the Mnemo distribution.
Prerequisites
=============
To function properly, Mnemo **requires** the following:
1. A working Horde installation.
Mnemo runs within the `Horde Application Framework`_, a set of common tools
for web applications written in PHP. You must install Horde before
installing Mnemo.
.. Important:: Mnemo H5 requires version 5.0+ of the Horde Framework -
earlier versions of Horde will **not** work.
.. Important:: Be sure to have completed all of the steps in the
`horde/docs/INSTALL`_ file for the Horde Framework before
installing Mnemo. Many of Mnemo's prerequisites are also
Horde prerequisites. Additionally, many of Mnemo's optional
features are configured via the Horde install.
.. _`Horde Application Framework`: http://www.horde.org/apps/horde
2. SQL support in PHP *or* a configured Kolab Server.
Mnemo will store its data in either an SQL database or on a Kolab Server.
If you use SQL, build PHP with whichever SQL driver you require; see the
Horde INSTALL_ file for details.
Installing Mnemo
================
The **RECOMMENDED** way to install Mnemo is using the PEAR installer.
Alternatively, if you want to run the latest development code or get the
latest not yet released fixes, you can install Mnemo from Git.
Installing with PEAR
~~~~~~~~~~~~~~~~~~~~
First follow the instructions in `horde/docs/INSTALL`_ to prepare a PEAR
environment for Horde and install the Horde Framework.
When installing Mnemo through PEAR now, the installer will automatically
install any dependencies of Mnemo too. If you want to install Mnemo with all
optional dependencies, but without the binary PECL packages that need to be
compiled, specify both the ``-a`` and the ``-B`` flag::
pear install -a -B horde/mnemo
By default, only the required dependencies will be installed::
pear install horde/mnemo
If you want to install Mnemo even with all binary dependencies, you need to
remove the ``-B`` flag. Please note that this might also try to install PHP
extensions through PECL that might need further configuration or activation in
your PHP configuration::
pear install -a horde/mnemo
Installing from Git
~~~~~~~~~~~~~~~~~~~
See http://www.horde.org/source/git.php
Configuring Mnemo
=================
1. Configuring Horde for Mnemo
Mnemo requires a permanent ``Shares`` backend in Horde to manage notepads
and to add notes to notepads. If you didn't setup a Share backend yet, go
to the configuration interface, select Horde from the list of applications
and select the ``Shares`` tab. Unless you are using Kolab, you should select
``SQL``.
2. Configuring Mnemo
You must login to Horde as a Horde Administrator to finish the
configuration of Mnemo. Use the Horde ``Administration`` menu item to get
to the administration page, and then click on the ``Configuration`` icon to
get the configuration page. Select ``Notes`` from the selection list of
applications. Fill in or change any configuration values as needed. When
done click on ``Generate Notes Configuration`` to generate the ``conf.php``
file. If your web server doesn't have write permissions to the Mnemo
configuration directory or file, it will not be able to write the file. In
this case, go back to ``Configuration`` and choose one of the other methods
to create the configuration file ``mnemo/config/conf.php``.
Documentation on the format and purpose of the other configuration files in
the ``config/`` directory can be found in each file. You may create
``*.local.php`` versions of these files if you wish to customize Mnemo's
appearance and behavior. See the header of the configuration files for
details and examples. The defaults will be correct for most sites.
3. Creating the database table
Once you finished the configuration in the previous step, you can create all
database tables by clicking the ``DB schema is out of date.`` link in the
Mnemo row of the configuration screen.
Alternatively you creating the Mnemo database tables can be accomplished with
horde's ``horde-db-migrate`` utility. If your database is properly setup in
the Horde configuration, just run the following::
horde/bin/horde-db-migrate mnemo
4. Testing Mnemo
Use Mnemo to create, modify, and delete notes. Test at least the following:
- Creating a new note
- Modifying a note
- Deleting a note
Obtaining Support
=================
If you encounter problems with Mnemo, help is available!
The Horde Frequently Asked Questions List (FAQ), available on the Web at
http://wiki.horde.org/FAQ
The Horde Project runs a number of mailing lists, for individual applications
and for issues relating to the project as a whole. Information, archives, and
subscription information can be found at
http://www.horde.org/community/mail
Lastly, Horde developers, contributors and users may also be found on IRC,
on the channel #horde on the Freenode Network (irc.freenode.net).
Please keep in mind that Mnemo is free software written by volunteers. For
information on reasonable support expectations, please read
http://www.horde.org/community/support
Thanks for using Mnemo!
The Horde team
.. _README: README
.. _INSTALL:
.. _`horde/docs/INSTALL`: ../../horde/docs/INSTALL
.. _`horde/docs/TRANSLATIONS`: ../../horde/docs/TRANSLATIONS
mnemo-4.2.9/docs/RELEASE_NOTES 0000664 0001750 0001750 00000001717 12654116457 013671 0 ustar jan jan Configuration and update anything that's highlighted as
outdated.
Upgrading Mnemo from 2.2.1 to 2.2.2
===================================
The group_uid field in the SQL share driver groups table has been changed from
an INT to a VARCHAR(255). Execute the provided SQL script to update your
database if you are using the native SQL share driver.
mysql --user=root --password= < scripts/upgrades/2.2.1_to_2.2.2.sql
Upgrading Mnemo from 2.2 to 2.2.1
=================================
The share_owner field in the SQL share driver table has been changed from a
VARCHAR(32) to a VARCHAR(255). Execute the provided SQL script to update your
database if you are using the native SQL share driver.
mysql --user=root --password= < scripts/upgrades/2.2_to_2.2.1.sql
Upgrading Mnemo from 2.x to 2.2
===============================
New Beta SQL Share Driver Support
---------------------------------
A new beta-level SQL Horde_Share driver has been added in Horde 3.2. This driver
offers significant performance improvements over the existing Datatree driver,
but it has not received the same level of testing, thus the beta designation.
In order to make use of this driver, you must be using Horde 3.2-RC3 or
later. To create the new tables needed for this driver, execute the provided SQL
script::
mysql --user=root --password= < scripts/upgrades/2.1_to_2.2.sql
If you want to use the new SQL Share driver, you must also execute the
provided PHP script to migrate your existing share data to the new format::
mnemo-convert-datatree-shares-to-sql
.. _INSTALL: INSTALL
mnemo-4.2.9/js/list.js 0000664 0001750 0001750 00000003172 12654116457 012710 0 ustar jan jan /**
* Code for the list view.
*
* Copyright 2013-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @package Mnemo
* @author Jan Schneider
*/
var Mnemo_List = {
// Externally set properties:
// ajaxUrl
sortCallback: function(column, sortDown)
{
new Ajax.Request(
this.ajaxUrl,
{ parameters: { pref: 'sortby', value: column.substring(1) } }
);
new Ajax.Request(
this.ajaxUrl,
{ parameters: { pref: 'sortdir', value: sortDown } }
);
},
onDomLoad: function()
{
if ($('quicksearchL')) {
$('quicksearchL').observe(
'click',
function(e) {
$('quicksearchL').hide();
$('quicksearch').show();
$('quicksearchT').focus();
e.stop();
}.bindAsEventListener()
);
$('quicksearchX').observe(
'click',
function(e) {
$('quicksearch').hide();
$('quicksearchT').value = '';
QuickFinder.filter($('quicksearchT'));
$('quicksearchL').show();
e.stop();
}.bindAsEventListener()
);
}
}
};
function table_sortCallback(tableId, column, sortDown)
{
Mnemo_List.sortCallback(column, sortDown);
}
document.observe('dom:loaded', Mnemo_List.onDomLoad.bind(Mnemo_List));
mnemo-4.2.9/js/memo.js 0000664 0001750 0001750 00000003035 12654116457 012670 0 ustar jan jan /**
* Code for mnemo/memo.php.
*
* Copyright 2013-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @package Mnemo
* @author Jan Schneider
*/
var Mnemo_Memo = {
// Externally set properties:
// confirm
updateCharacterCount: function()
{
if ($('mnemo-body')) {
$('mnemo-count').update(
$F('mnemo-body').replace(/[\r\n]/g, '').length
);;
}
},
onDomLoad: function()
{
if ($('mnemo-passphrase')) {
$('mnemo-passphrase').focus();
}
if ($('mnemo-body')) {
$('mnemo-body').focus();
}
if ($('mnemo-delete')) {
$('mnemo-delete').observe(
'click',
function(e)
{
if (this.confirm) {
if (!window.confirm(this.confirm)) {
e.stop();
}
}
}.bindAsEventListener(this)
);
}
if ($('mnemo-body')) {
$('mnemo-body').observe('change', this.updateCharacterCount);
$('mnemo-body').observe('click', this.updateCharacterCount);
$('mnemo-body').observe('keypress', this.updateCharacterCount.defer.bind(this.updateCharacterCount));
}
}
}
document.observe('dom:loaded', Mnemo_Memo.onDomLoad.bind(Mnemo_Memo));
mnemo-4.2.9/js/view.js 0000664 0001750 0001750 00000001720 12654116457 012704 0 ustar jan jan /**
* Code for mnemo/view.php.
*
* Copyright 2013-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @package Mnemo
* @author Jan Schneider
*/
var Mnemo_View = {
// Externally set properties:
// confirm
onDomLoad: function()
{
if ($('mnemo-passphrase')) {
$('mnemo-passphrase').focus();
}
if ($('mnemo-delete')) {
$('mnemo-delete').observe(
'click',
function(e)
{
if (this.confirm) {
if (!window.confirm(this.confirm)) {
e.stop();
}
}
}.bindAsEventListener(this)
);
}
}
}
document.observe('dom:loaded', Mnemo_View.onDomLoad.bind(Mnemo_View));
mnemo-4.2.9/lib/Ajax/Imple/EditNote.php 0000664 0001750 0001750 00000002343 12654116457 015705 0 ustar jan jan
* @category Horde
* @package Mnemo
*/
class Mnemo_Ajax_Imple_EditNote extends Horde_Core_Ajax_Imple_InPlaceEditor
{
/**
*/
protected function _handleEdit(Horde_Variables $vars)
{
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
$memo = $storage->getByUID($vars->id);
/* Are we requesting the unformatted text? */
if ($vars->action == 'load') {
return $memo['body'];
}
$share = $GLOBALS['mnemo_shares']->getShare($memo['memolist_id']);
if (!$share->hasPermission($GLOBALS['registry']->getAuth(), Horde_Perms::EDIT)) {
throw new Horde_Exception_PermissionDenied(_("You do not have permission to edit this note."));
}
$storage->modify($memo['memo_id'], $memo['desc'], $vars->{$vars->input});
return $GLOBALS['injector']->getInstance('Horde_Core_Factory_TextFilter')->filter(
$vars->{$vars->input},
'text2html',
array('parselevel' => Horde_Text_Filter_Text2html::MICRO)
);
}
}
mnemo-4.2.9/lib/Ajax/Imple/TagAutoCompleter.php 0000664 0001750 0001750 00000002044 12654116457 017407 0 ustar jan jan
* @author Jan Schneider
* @package Mnemo
*/
class Mnemo_Ajax_Imple_TagAutoCompleter extends Horde_Core_Ajax_Imple_AutoCompleter
{
/**
*/
protected function _getAutoCompleter()
{
$opts = array();
foreach (array('box', 'triggerContainer') as $val) {
if (isset($this->_params[$val])) {
$opts[$val] = $this->_params[$val];
}
}
return empty($this->_params['pretty'])
? new Horde_Core_Ajax_Imple_AutoCompleter_Ajax($opts)
: new Horde_Core_Ajax_Imple_AutoCompleter_Pretty($opts);
}
/**
*/
protected function _handleAutoCompleter($input)
{
return array_values($GLOBALS['injector']->getInstance('Mnemo_Tagger')->listTags($input));
}
}
mnemo-4.2.9/lib/Ajax/Application.php 0000664 0001750 0001750 00000001240 12654116457 015362 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/apache ASL
* @package Mnemo
*/
class Mnemo_Ajax_Application extends Horde_Core_Ajax_Application
{
/**
*/
protected function _init()
{
$this->addHandler('Horde_Core_Ajax_Application_Handler_Imple');
$this->addHandler('Horde_Core_Ajax_Application_Handler_Prefs');
}
}
mnemo-4.2.9/lib/Block/Note.php 0000664 0001750 0001750 00000006032 12654116457 014177 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Block_Note extends Horde_Core_Block
{
/**
*/
private $_notename = '';
/**
*/
public function __construct($app, $params = array())
{
parent::__construct($app, $params);
$this->_name = _("View note");
}
/**
*/
protected function _params()
{
global $prefs;
$memos = Mnemo::listMemos($prefs->getValue('sortby'),
$prefs->getValue('sortdir'));
$notes = array();
foreach ($memos as $memo) {
$notes[$memo['uid']] = $memo['desc'];
}
return array(
'note_uid' => array(
'type' => 'enum',
'name' => _("Show this note"),
'values' => $notes,
)
);
}
/**
*/
protected function _title()
{
return htmlspecialchars($this->_getTitle());
}
/**
*/
protected function _content()
{
$memo = $this->_getNote();
$html = '';
$body = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_TextFilter')
->filter(
$memo['body'],
'text2html',
array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
try {
$body = Horde::callHook('format_description', array($body), 'mnemo', $body);
} catch (Horde_Exception_HookNotSet $e) {}
$html .= $body . '
';
$GLOBALS['injector']->getInstance('Horde_Core_Factory_Imple')
->create('Mnemo_Ajax_Imple_EditNote', array(
'dataid' => $this->_params['note_uid'],
'id' => 'noteBody' . $memo['memo_id'],
'rows' => substr_count($memo['body'], "\n")));
return $html;
}
/**
*/
private function _getNote()
{
if (!isset($this->_params['note_uid'])) {
throw new Horde_Exception(_("No note loaded"));
}
$uid = $this->_params['note_uid'];
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
try {
$memo = $storage->getByUID($uid);
} catch (Mnemo_Exception $e) {
if (!empty($this->_notename)) {
$msg = sprintf(_("An error occurred displaying %s"), $this->_notename);
} else {
$msg = _("An error occurred displaying the note");
}
throw new Horde_Exception($msg);
}
return $memo;
}
/**
*/
private function _getTitle()
{
if (empty($this->_notename)) {
$note = $this->_getNote();
$this->_notename = $note['desc'];
}
return $this->_notename;
}
}
mnemo-4.2.9/lib/Block/Summary.php 0000664 0001750 0001750 00000006175 12654116457 014737 0 ustar jan jan _name = _("Notes Summary");
}
/**
*/
protected function _title()
{
global $registry;
$label = !empty($this->_params['block_title'])
? $this->_params['block_title']
: $registry->get('name');
return Horde::link(Horde::url($registry->getInitialPage(), true))
. htmlspecialchars($label) . '';
}
/**
*/
protected function _params()
{
return array(
'show_actions' => array(
'type' => 'checkbox',
'name' => _("Show action buttons?"),
'default' => 1
),
'show_notepad' => array(
'type' => 'checkbox',
'name' => _("Show notepad name?"),
'default' => 1
),
);
}
/**
*/
protected function _content()
{
global $registry, $prefs;
if (!empty($this->_params['show_notepad'])) {
$shares = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create();
}
$html = '';
$memos = Mnemo::listMemos($prefs->getValue('sortby'),
$prefs->getValue('sortdir'));
foreach ($memos as $id => $memo) {
$html .= '';
if (!empty($this->_params['show_actions'])) {
$editImg = Horde_Themes::img('edit.png');
$editurl = Horde::url('memo.php')->add(array('memo' => $memo['memo_id'], 'memolist' => $memo['memolist_id']));
$html .= ''
. Horde::link(htmlspecialchars(Horde::url($editurl, true)->add('actionID', 'modify_memo')), _("Edit Note"))
. Horde::img($editImg, _("Edit Note"))
. ' | ';
}
if (!empty($this->_params['show_notepad'])) {
$html .= '' . htmlspecialchars(Mnemo::getLabel($shares->getShare($memo['memolist_id']))) . ' | ';
}
$viewurl = Horde::url('view.php')->add(
array('memo' => $memo['memo_id'],
'memolist' => $memo['memolist_id']));
$html .= ''
. Horde::linkTooltip(
htmlspecialchars(Horde::url($viewurl, true)),
'', '', '', '',
$memo['body'] != $memo['desc'] ? Mnemo::getNotePreview($memo) : '')
. (strlen($memo['desc']) ? htmlspecialchars($memo['desc']) : '' . _("Empty Note") . '')
. ' |
';
}
if (!$memos) {
return '' . _("No notes to display") . '
';
}
return '';
}
}
mnemo-4.2.9/lib/Driver/Kolab.php 0000664 0001750 0001750 00000025622 12654116457 014531 0 ustar jan jan
* @author Thomas Jarosch
* @author Stuart Binge
* @since Mnemo 2.0
* @package Mnemo
*/
class Mnemo_Driver_Kolab extends Mnemo_Driver
{
/**
* The Kolab_Storage backend.
*
* @var Horde_Kolab_Storage
*/
private $_kolab;
/**
* The current notepad.
*
* @var Horde_Kolab_Storage_Data
*/
private $_data;
/**
* Construct a new Kolab storage object.
*
* @param string $notepad The name of the notepad to load/save notes from.
* @param array $params The connection parameters
*
* @throws InvalidArguementException
*/
public function __construct($notepad, $params = array())
{
if (empty($params['storage'])) {
throw new InvalidArgumentException('Missing required storage handler.');
}
$this->_notepad = $notepad;
$this->_kolab = $params['storage'];
}
/**
* Retrieves all of the notes of the current notepad from the backend.
*
* @throws Mnemo_Exception
*/
public function retrieve()
{
$this->_memos = array();
try {
$note_list = $this->_getData()->getObjects();
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
if (empty($note_list)) {
return;
}
foreach ($note_list as $note) {
$this->_memos[Horde_Url::uriB64Encode($note['uid'])] = $this->_buildNote($note);
}
}
/**
* Retrieves one note from the backend.
*
* @param string $noteId The ID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
public function get($noteId, $passphrase = null)
{
try {
$uid = Horde_Url::uriB64Decode($noteId);
if ($this->_getData()->objectIdExists($uid)) {
$note = $this->_getData()->getObject($uid);
return $this->_buildNote($note, $passphrase);
} else {
throw new Horde_Exception_NotFound();
}
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
}
/**
* Retrieves one note from the backend by UID.
*
* @param string $uid The UID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
public function getByUID($uid, $passphrase = null)
{
//@todo: search across notepads
// HACK: Use default notepad if no notepad is set.
// ActiveSync does not work without this
// as we don't search across all notepads yet.
if (empty($this->_notepad)) {
$this->_notepad = Mnemo::getDefaultNotepad();
}
return $this->get(Horde_Url::uriB64Encode($uid), $passphrase);
}
/**
* Adds a note to the backend storage.
*
* @param string $noteId The ID of the new note.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return string The unique ID of the new note.
* @throws Mnemo_Exception
*/
protected function _add($noteId, $desc, $body, $tags)
{
$object = $this->_buildObject($noteId, $desc, $body, $tags);
try {
$this->_getData()->create($object);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
return $object['uid'];
}
/**
* Modifies an existing note.
*
* @param string $noteId The note to modify.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
protected function _modify($noteId, $desc, $body, $tags)
{
$object = $this->_buildObject($noteId, $desc, $body, $tags);
try {
$this->_getData()->modify($object);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
return $object['uid'];
}
/**
* Converts a note hash to a Kolab hash.
*
* @param string $noteId The note to modify.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return object The Kolab hash.
*/
protected function _buildObject($noteId, $desc, $body, $tags)
{
$uid = Horde_Url::uriB64Decode($noteId);
$object = array(
'uid' => $uid,
'summary' => $desc,
'body' => $body,
);
$object['categories'] = $GLOBALS['injector']
->getInstance('Mnemo_Tagger')
->split($tags);
usort($object['categories'], 'strcoll');
return $object;
}
/**
* Moves a note to a new notepad.
*
* @param string $noteId The note to move.
* @param string $newNotepad The new notepad.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
protected function _move($noteId, $newNotepad)
{
$uid = Horde_Url::uriB64Decode($noteId);
try {
$this->_getData()->move(
$uid,
$GLOBALS['mnemo_shares']->getShare($newNotepad)->get('folder')
);
$this->_getDataForNotepad($newNotepad)->synchronize();
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
return $uid;
}
/**
* Deletes a note permanently.
*
* @param array $note The note to delete.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
protected function _delete($noteId)
{
$uid = Horde_Url::uriB64Decode($noteId);
try {
$this->_getData()->delete($uid);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
return $uid;
}
/**
* Deletes all notes from the current notepad.
*
* @return array An array of uids that have been removed.
* @throws Mnemo_Exception
*/
protected function _deleteAll()
{
try {
$uids = $this->_getData()->getObjectIds();
$this->_getData()->deleteAll();
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception($e);
}
return $uids;
}
/**
* Return the Kolab data handler for the current notepad.
*
* @return Horde_Kolab_Storage_Data The data handler.
*/
protected function _getData()
{
if (empty($this->_notepad)) {
throw new LogicException(
'The notepad has been left undefined but is required!'
);
}
if ($this->_data === null) {
$this->_data = $this->_getDataForNotepad($this->_notepad);
}
return $this->_data;
}
/**
* Return the Kolab data handler for the specified notepad.
*
* @param string $notepad The notepad name.
*
* @return Horde_Kolab_Storage_Data The data handler.
*/
protected function _getDataForNotepad($notepad)
{
try {
return $this->_kolab->getData(
$GLOBALS['mnemo_shares']->getShare($notepad)->get('folder'),
'note'
);
} catch (Horde_Kolab_Storage_Exception $e) {
throw new Mnemo_Exception(
sprintf(
_("Failed retrieving Kolab data for notepad %s: %s"),
$notepad,
$e->getMessage()
)
);
}
}
/**
* Build a note based on data array
*
* @param array $note The data for the note
* @param string $passphrase A passphrase for decrypting a note
*
* @return array The converted data array representing the note
*/
protected function _buildNote($note, $passphrase = null)
{
$encrypted = false;
$body = $note['body'];
$id = Horde_Url::uriB64Encode($note['uid']);
if (strpos($body, '-----BEGIN PGP MESSAGE-----') === 0) {
$encrypted = true;
if (empty($passphrase)) {
$passphrase = Mnemo::getPassphrase($id);
}
if (empty($passphrase)) {
$body = new Mnemo_Exception(_("This note has been encrypted."), Mnemo::ERR_NO_PASSPHRASE);
} else {
try {
$body = $this->_decrypt($body, $passphrase)->message;
} catch (Mnemo_Exception $e) {
$body = $e;
}
Mnemo::storePassphrase($id, $passphrase);
}
}
$tagger = $GLOBALS['injector']->getInstance('Mnemo_Tagger');
$tags = $tagger->getTags($note['uid'], 'note');
if (!empty($note['categories'])) {
usort($tags, 'strcoll');
if (array_diff($note['categories'], $tags)) {
$tagger->replaceTags(
$note['uid'],
$note['categories'],
$GLOBALS['registry']->getAuth(),
'note'
);
}
$tags = $note['categories'];
}
$result = array(
'memolist_id' => $this->_notepad,
'memo_id' => $id,
'uid' => $note['uid'],
'tags' => $tags,
'desc' => $note['summary'],
'encrypted' => $encrypted,
'body' => $body,
);
if (!empty($note['creation-date'])) {
$result['created'] = new Horde_Date($note['creation-date']);
}
if (!empty($note['last-modification-date'])) {
$result['modified'] = new Horde_Date($note['last-modification-date']);
}
return $result;
}
/**
* Generates a local note ID.
*
* @return string A new note ID.
*/
protected function _generateId()
{
return Horde_Url::uriB64Encode($this->_getData()->generateUid());
}
}
mnemo-4.2.9/lib/Driver/Sql.php 0000664 0001750 0001750 00000030335 12654116457 014235 0 ustar jan jan
* @author Michael J. Rubinsky
* @package Mnemo
*/
class Mnemo_Driver_Sql extends Mnemo_Driver
{
/**
* The database connection object.
*
* @var Horde_Db_Adapter
*/
protected $_db;
/**
* Share table name
*
* @var string
*/
protected $_table;
/**
* Charset
*
* @var string
*/
protected $_charset;
/**
* Column definition of body column.
*
* @var Horde_Db_Adapter_Base_Column
*/
protected $_column;
/**
* Construct a new SQL storage object.
*
* @param string $notepad The name of the notepad to load/save notes from.
* @param array $params The connection parameters
*
* @throws InvalidArguementException
*/
public function __construct($notepad, $params = array())
{
if (empty($params['db']) || empty($params['table'])) {
throw new InvalidArgumentException('Missing required connection parameter(s).');
}
$this->_notepad = $notepad;
$this->_db = $params['db'];
$this->_table = $params['table'];
$this->_charset = $params['charset'];
$this->_column = $this->_db->column($params['table'], 'memo_body');
}
/**
* Retrieves all of the notes of the current notepad from the backend.
*
* @throws Mnemo_Exception
*/
public function retrieve()
{
$query = sprintf('SELECT * FROM %s WHERE memo_owner = ?', $this->_table);
$values = array($this->_notepad);
try {
$rows = $this->_db->selectAll($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
// Store the retrieved values in a fresh list.
$this->_memos = array();
foreach ($rows as $row) {
$this->_memos[$row['memo_id']] = $this->_buildNote($row);
}
}
/**
* Retrieves one note from the backend.
*
* @param string $noteId The ID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
public function get($noteId, $passphrase = null)
{
$query = 'SELECT * FROM ' . $this->_table .
' WHERE memo_owner = ? AND memo_id = ?';
$values = array($this->_notepad, $noteId);
try {
$row = $this->_db->selectOne($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
if (!$row) {
throw new Horde_Exception_NotFound();
}
return $this->_buildNote($row, $passphrase);
}
/**
* Retrieves one note from the backend by UID.
*
* @param string $uid The UID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
public function getByUID($uid, $passphrase = null)
{
$query = 'SELECT * FROM ' . $this->_table . ' WHERE memo_uid = ?';
$values = array($uid);
try {
$row = $this->_db->selectOne($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
if (!count($row)) {
throw new Horde_Exception_NotFound('Not found');
}
$this->_notepad = $row['memo_owner'];
return $this->_buildNote($row, $passphrase);
}
/**
* Adds a note to the backend storage.
*
* @param string $noteId The ID of the new note.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return string The unique ID of the new note.
* @throws Mnemo_Exception
*/
protected function _add($noteId, $desc, $body, $tags)
{
$uid = strval(new Horde_Support_Uuid());
$query = 'INSERT INTO ' . $this->_table
. ' (memo_owner, memo_id, memo_desc, memo_body, memo_uid)'
. ' VALUES (?, ?, ?, ?, ?)';
$values = array(
$this->_notepad,
$noteId,
Horde_String::convertCharset($desc, 'UTF-8', $this->_charset),
Horde_String::convertCharset($body, 'UTF-8', $this->_charset),
Horde_String::convertCharset($uid, 'UTF-8', $this->_charset)
);
try {
$this->_db->insert($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e);
}
return $uid;
}
/**
* Modifies an existing note.
*
* @param string $noteId The note to modify.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @throws Mnemo_Exception
*/
protected function _modify($noteId, $desc, $body, $tags)
{
$query = 'UPDATE ' . $this->_table
. ' SET memo_desc = ?, memo_body = ?'
. ' WHERE memo_owner = ? AND memo_id = ?';
$values = array(
Horde_String::convertCharset($desc, 'UTF-8', $this->_charset),
Horde_String::convertCharset($body, 'UTF-8', $this->_charset),
$this->_notepad,
$noteId
);
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e);
}
$note = $this->get($noteId);
return $note['uid'];
}
/**
* Moves a note to a new notepad.
*
* @param string $noteId The note to move.
* @param string $newNotepad The new notepad.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
protected function _move($noteId, $newNotepad)
{
// Get the note's details for use later.
$note = $this->get($noteId);
$query = 'UPDATE ' . $this->_table .
' SET memo_owner = ?' .
' WHERE memo_owner = ? AND memo_id = ?';
$values = array($newNotepad, $this->_notepad, $noteId);
try {
$result = $this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
return $note['uid'];
}
/**
* Deletes a note permanently.
*
* @param array $note The note to delete.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
protected function _delete($noteId)
{
// Get the note's details for use later.
$note = $this->get($noteId);
$query = 'DELETE FROM ' . $this->_table .
' WHERE memo_owner = ? AND memo_id = ?';
$values = array($this->_notepad, $noteId);
try {
$this->_db->delete($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
return $note['uid'];
}
/**
* Deletes all notes from the current notepad.
*
* @return array An array of uids that have been removed.
* @throws Mnemo_Exception
*/
protected function _deleteAll()
{
// Get list of notes we are removing so we can tell history about it.
$query = sprintf('SELECT memo_uid FROM %s WHERE memo_owner = ?',
$this->_table);
$values = array($this->_notepad);
try {
$ids = $this->_db->selectValues($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
$query = sprintf('DELETE FROM %s WHERE memo_owner = ?', $this->_table);
try {
$this->_db->delete($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
return $ids;
}
/**
*
* @param array $row Hash of the note data, db keys.
* @param string $passphrase The encryption passphrase.
*
* @return array a Task hash.
* @throws Mnemo_Exception
*/
protected function _buildNote($row, $passphrase = null)
{
// Make sure notes always have a UID.
if (empty($row['memo_uid'])) {
$row['memo_uid'] = strval(new Horde_Support_Guid());
$query = 'UPDATE ' . $this->_table .
' SET memo_uid = ?' .
' WHERE memo_owner = ? AND memo_id = ?';
$values = array($row['memo_uid'], $row['memo_owner'], $row['memo_id']);
try {
$this->_db->update($query, $values);
} catch (Horde_Db_Exception $e) {
throw new Mnemo_Exception($e->getMessage());
}
}
// Decrypt note if requested.
$encrypted = false;
$body = $this->_column->binaryToString($row['memo_body']);
$body = Horde_String::convertCharset($body, $this->_charset, 'UTF-8');
if (strpos($body, '-----BEGIN PGP MESSAGE-----') === 0) {
$encrypted = true;
if (empty($passphrase)) {
$passphrase = Mnemo::getPassphrase($row['memo_id']);
}
if (empty($passphrase)) {
$body = new Mnemo_Exception(_("This note has been encrypted."), Mnemo::ERR_NO_PASSPHRASE);
} else {
try {
$body = $this->_decrypt($body, $passphrase);
$body = $body->message;
} catch (Mnemo_Exception $e) {
$body = $e;
}
Mnemo::storePassphrase($row['memo_id'], $passphrase);
}
}
// Create a new note based on $row's values.
$uid = Horde_String::convertCharset(
$row['memo_uid'], $this->_charset, 'UTF-8'
);
$memo = array(
'memolist_id' => $row['memo_owner'],
'memo_id' => $row['memo_id'],
'uid' => $uid,
'desc' => Horde_String::convertCharset(
$row['memo_desc'], $this->_charset, 'UTF-8'),
'body' => $body,
'tags' => $GLOBALS['injector']->getInstance('Mnemo_Tagger')->getTags($uid, 'note'),
'encrypted' => $encrypted);
try {
$userId = $GLOBALS['registry']->getAuth();
$log = $GLOBALS['injector']->getInstance('Horde_History')
->getHistory('mnemo:' . $row['memo_owner'] . ':' . $row['memo_uid']);
foreach ($log as $entry) {
switch ($entry['action']) {
case 'add':
$memo['created'] = new Horde_Date($entry['ts']);
if ($userId != $entry['who']) {
$memo['createdby'] = sprintf(_("by %s"), Mnemo::getUserName($entry['who']));
} else {
$memo['createdby'] = _("by me");
}
break;
case 'modify':
$memo['modified'] = new Horde_Date($entry['ts']);
if ($userId != $entry['who']) {
$memo['modifiedby'] = sprintf(_("by %s"), Mnemo::getUserName($entry['who']));
} else {
$memo['modifiedby'] = _("by me");
}
break;
}
}
} catch (Horde_Exception $e) {
}
return $memo;
}
/**
* Generates a local note ID.
*
* @return string A new note ID.
*/
protected function _generateId()
{
return strval(new Horde_Support_Randomid());
}
}
mnemo-4.2.9/lib/Factory/Driver.php 0000664 0001750 0001750 00000004357 12654116457 015112 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Factory_Driver
{
/**
* Instances.
*
* @var array
*/
private $_instances = array();
/**
* The injector.
*
* @var Horde_Injector
*/
private $_injector;
/**
* Constructor.
*
* @param Horde_Injector $injector The injector to use.
*/
public function __construct(Horde_Injector $injector)
{
$this->_injector = $injector;
}
/**
* Return the Mnemo_Driver:: instance.
*
* @param mixed $name The notepad to open
*
* @return Mnemo_Driver
* @throws Mnemo_Exception
*/
public function create($name = '')
{
if (!isset($this->_instances[$name])) {
$driver = $GLOBALS['conf']['storage']['driver'];
$params = Horde::getDriverConfig('storage', $driver);
$class = 'Mnemo_Driver_' . ucfirst(basename($driver));
if (!class_exists($class)) {
throw new Mnemo_Exception(sprintf('Unable to load the definition of %s.', $class));
}
switch ($class) {
case 'Mnemo_Driver_Sql':
if ($params['driverconfig'] != 'horde') {
$customParams = $params;
unset($customParams['driverconfig'], $customParams['table']);
$params['db'] = $this->_injector->getInstance('Horde_Core_Factory_Db')->create('mnemo', $customParams);
} else {
$params['db'] = $this->_injector->getInstance('Horde_Db_Adapter');
}
break;
case 'Mnemo_Driver_Kolab':
$params = array(
'storage' => $this->_injector->getInstance('Horde_Kolab_Storage')
);
}
$driver = new $class($name, $params);
$this->_instances[$name] = $driver;
}
return $this->_instances[$name];
}
}
mnemo-4.2.9/lib/Factory/Notepads.php 0000664 0001750 0001750 00000004574 12654116457 015435 0 ustar jan jan
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
/**
* The factory for the notepads handler.
*
* Copyright 2011-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @category Horde
* @package Mnemo
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
class Mnemo_Factory_Notepads
{
/**
* Notepads drivers already created.
*
* @var array
*/
private $_instances = array();
/**
* The injector.
*
* @var Horde_Injector
*/
private $_injector;
/**
* Constructor.
*
* @param Horde_Injector $injector The injector to use.
*/
public function __construct(Horde_Injector $injector)
{
$this->_injector = $injector;
}
/**
* Return a Mnemo_Notepads instance.
*
* @return Mnemo_Notepads
*/
public function create()
{
if (!isset($GLOBALS['conf']['notepads']['driver'])) {
$driver = 'Default';
} else {
$driver = Horde_String::ucfirst($GLOBALS['conf']['notepads']['driver']);
}
if (empty($this->_instances[$driver])) {
$class = 'Mnemo_Notepads_' . $driver;
if (class_exists($class)) {
$params = array();
if (!empty($GLOBALS['conf']['share']['auto_create'])) {
$params['auto_create'] = true;
}
switch ($driver) {
case 'Default':
$params['identity'] = $this->_injector->getInstance('Horde_Core_Factory_Identity')->create();
break;
}
$this->_instances[$driver] = new $class(
$GLOBALS['mnemo_shares'],
$GLOBALS['registry']->getAuth(),
$params
);
} else {
throw new Mnemo_Exception(sprintf('Unable to load the definition of %s.', $class));
}
}
return $this->_instances[$driver];
}
} mnemo-4.2.9/lib/Form/CreateNotepad.php 0000664 0001750 0001750 00000002664 12654116457 015670 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Form_CreateNotepad extends Horde_Form
{
public function __construct(&$vars)
{
parent::__construct($vars, _("Create Notepad"));
$this->addVariable(_("Name"), 'name', 'text', true);
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
$this->setButtons(array(_("Create")));
}
public function execute()
{
// Create new share.
try {
$notepad = $GLOBALS['mnemo_shares']->newShare($GLOBALS['registry']->getAuth(), strval(new Horde_Support_Uuid()), $this->_vars->get('name'));
$notepad->set('desc', $this->_vars->get('description'));
$GLOBALS['mnemo_shares']->addShare($notepad);
$GLOBALS['display_notepads'][] = $notepad->getName();
$GLOBALS['prefs']->setValue('display_notepads', serialize($GLOBALS['display_notepads']));
} catch (Horde_Share_Exception $e) {
Horde::log($e->getMessage(), 'ERR');
throw new Mnemo_Exception($e);
}
return $notepad;
}
}
mnemo-4.2.9/lib/Form/DeleteNotepad.php 0000664 0001750 0001750 00000004057 12654116457 015665 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Form_DeleteNotepad extends Horde_Form
{
/**
* Notepad being deleted
*/
protected $_notepad;
/**
* Const'r
*/
public function __construct(&$vars, $notepad)
{
$this->_notepad = $notepad;
parent::__construct($vars, sprintf(_("Delete %s"), $notepad->get('name')));
$this->addHidden('', 'n', 'text', true);
$this->addVariable(sprintf(_("Really delete the notepad \"%s\"? This cannot be undone and all data on this notepad will be permanently removed."), htmlspecialchars($this->_notepad->get('name'))), 'desc', 'description', false);
$this->setButtons(array(
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel")),
));
}
public function execute()
{
// If cancel was clicked, return false.
if ($this->_vars->get('submitbutton') == _("Cancel")) {
Horde::url('', true)->redirect();
}
if (!$GLOBALS['registry']->getAuth() ||
$this->_notepad->get('owner') != $GLOBALS['registry']->getAuth()) {
throw new Horde_Exception_PermissionDenied(_("Permission denied"));
}
// Delete the notepad.
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($this->_notepad->getName());
$result = $storage->deleteAll();
// Remove share and all groups/permissions.
try {
$GLOBALS['mnemo_shares']->removeShare($this->_notepad);
} catch (Horde_Share_Exception $e) {
Horde::log($e->getMessage(), 'ERR');
throw new Mnemo_Exception($e->getMessage());
}
}
}
mnemo-4.2.9/lib/Form/EditNotepad.php 0000664 0001750 0001750 00000006343 12654116457 015350 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Form_EditNotepad extends Horde_Form
{
/**
* Notepad being edited
*/
protected $_notepad;
public function __construct($vars, $notepad)
{
$this->_notepad = $notepad;
$owner = $notepad->get('owner') == $GLOBALS['registry']->getAuth() ||
(is_null($notepad->get('owner')) &&
$GLOBALS['registry']->isAdmin());
parent::__construct(
$vars,
$owner
? sprintf(_("Edit %s"), $notepad->get('name'))
: $notepad->get('name')
);
$this->addHidden('', 'n', 'text', true);
$this->addVariable(_("Name"), 'name', 'text', true);
if (!$owner) {
$v = $this->addVariable(_("Owner"), 'owner', 'text', false);
$owner_name = $GLOBALS['injector']
->getInstance('Horde_Core_Factory_Identity')
->create($notepad->get('owner'))
->getValue('fullname');
if (trim($owner_name) == '') {
$owner_name = $notepad->get('owner');
}
$v->setDefault($owner_name ? $owner_name : _("System"));
}
$this->addVariable(_("Description"), 'description', 'longtext', false, false, null, array(4, 60));
/* Permissions link. */
if (empty($GLOBALS['conf']['share']['no_sharing']) && $owner) {
$url = Horde::url($GLOBALS['registry']->get('webroot', 'horde')
. '/services/shares/edit.php')
->add(array('app' => 'mnemo', 'share' => $notepad->getName()));
$this->addVariable(
'', '', 'link', false, false, null,
array(array(
'url' => $url,
'text' => _("Change Permissions"),
'onclick' => Horde::popupJs(
$url,
array('params' => array('urlencode' => true)))
. 'return false;',
'class' => 'horde-button',
'target' => '_blank')
)
);
}
$this->setButtons(array(
_("Save"),
array('class' => 'horde-delete', 'value' => _("Delete")),
array('class' => 'horde-cancel', 'value' => _("Cancel"))
));
}
public function execute()
{
switch ($this->_vars->submitbutton) {
case _("Save"):
$this->_notepad->set('name', $this->_vars->get('name'));
$this->_notepad->set('desc', $this->_vars->get('description'));
$this->_notepad->save();
break;
case _("Delete"):
Horde::url('notepads/delete.php')
->add('n', $this->_vars->n)
->redirect();
break;
case _("Cancel"):
Horde::url('', true)->redirect();
break;
}
}
}
mnemo-4.2.9/lib/Form/Search.php 0000664 0001750 0001750 00000002037 12654116457 014351 0 ustar jan jan
* @package Mnemo
*/
/**
* Notes search form.
*
* @author Jan Schneider
* @package Mnemo
*/
class Mnemo_Form_Search extends Horde_Form
{
public function __construct($vars)
{
parent::__construct($vars, _("Search"));
$this->addHidden('', 'actionID', 'text', false);
$this->addVariable(_("For"), 'search_pattern', 'text', false);
$v = $this->addVariable(
_("In"), 'search_type', 'radio', false, false, null,
array(array('desc' => _("Title"), 'body' => _("Body")))
);
$v->setDefault('desc');
$this->setButtons(_("Search"));
}
public function render()
{
$this->_vars->actionID = 'search_memos';
parent::renderActive(null, null, Horde::url('list.php'));
}
}
mnemo-4.2.9/lib/Notepads/Base.php 0000664 0001750 0001750 00000006601 12654116457 014671 0 ustar jan jan
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
/**
* The base functionality of the notepads handler.
*
* Copyright 2001-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @category Horde
* @package Mnemo
* @author Jon Parise
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
abstract class Mnemo_Notepads_Base
{
/**
* The share backend.
*
* @var Horde_Share_Base
*/
protected $_shares;
/**
* The current user.
*
* @var string
*/
protected $_user;
/**
* Additional parameters for the notepad handling.
*
* @var array
*/
protected $_params;
/**
* Constructor.
*
* @param Horde_Share_Base $shares The share backend.
* @param string $user The current user.
* @param array $params Additional parameters.
*/
public function __construct($shares, $user, $params)
{
$this->_shares = $shares;
$this->_user = $user;
$this->_params = $params;
}
/**
* Ensure the share system has a default notepad share for the current user
* if the default share feature is activated.
*
* @return string|NULL The id of the new default share or NULL if no share
* was created.
*/
public function ensureDefaultShare()
{
/* If the user doesn't own a notepad, create one. */
if (!empty($this->_params['auto_create']) && $this->_user &&
!count(Mnemo::listNotepads(true))) {
$share = $this->_shares->newShare(
$this->_user,
strval(new Horde_Support_Randomid()),
$this->_getDefaultShareName()
);
$this->_prepareDefaultShare($share);
$this->_shares->addShare($share);
return $share->getName();
}
}
/**
* Returns the default share's ID, if it can be determined from the share
* backend.
*
* @return string The default share ID.
*/
public function getDefaultShare()
{
$shares = $this->_shares->listShares(
$this->_user,
array('attributes' => $this->_user)
);
foreach ($shares as $id => $share) {
if ($share->get('default')) {
return $id;
}
}
}
/**
* Runs any actions after setting a new default tasklist.
*
* @param string $share The default share ID.
*/
public function setDefaultShare($share)
{
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
abstract protected function _getDefaultShareName();
/**
* Add any modifiers required to the share in order to mark it as default.
*
* @param Horde_Share_Object $share The new default share.
*/
protected function _prepareDefaultShare($share)
{
}
} mnemo-4.2.9/lib/Notepads/Default.php 0000664 0001750 0001750 00000003373 12654116457 015406 0 ustar jan jan
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
/**
* The default notepads handler.
*
* Copyright 2001-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @category Horde
* @package Mnemo
* @author Jon Parise
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
class Mnemo_Notepads_Default extends Mnemo_Notepads_Base
{
/**
* The current identity.
*
* @var Horde_Prefs_Identity
*/
private $_identity;
/**
* Constructor.
*
* @param Horde_Share_Base $shares The share backend.
* @param string $user The current user.
* @param array $params Additional parameters.
*/
public function __construct($shares, $user, $params)
{
if (!isset($params['identity'])) {
throw new BadMethodCallException('This notepad handler needs an "identity" parameter!');
} else {
$this->_identity = $params['identity'];
unset($params['identity']);
}
parent::__construct($shares, $user, $params);
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
protected function _getDefaultShareName()
{
return sprintf(_("Notepad of %s"), $this->_identity->getName());
}
}
mnemo-4.2.9/lib/Notepads/Kolab.php 0000664 0001750 0001750 00000003503 12654116457 015045 0 ustar jan jan
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
/**
* The Kolab specific notepads handler.
*
* Copyright 2011-2016 Horde LLC (http://www.horde.org/)
*
* See the enclosed file LICENSE for license information (ASL). If you
* did not receive this file, see http://www.horde.org/licenses/apache.
*
* @category Horde
* @package Mnemo
* @author Gunnar Wrobel
* @license http://www.horde.org/licenses/apache
* @link http://www.horde.org/apps/mnemo
*/
class Mnemo_Notepads_Kolab extends Mnemo_Notepads_Base
{
/**
* Runs any actions after setting a new default notepad.
*
* @param string $share The default share ID.
*/
public function setDefaultShare($share)
{
$notepads = $this->_shares
->listShares(
$this->_user,
array('perm' => Horde_Perms::SHOW,
'attributes' => $this->_user));
foreach ($notepads as $id => $notepad) {
if ($id == $share) {
$notepad->set('default', true);
$notepad->save();
break;
}
}
}
/**
* Return the name of the default share.
*
* @return string The name of a default share.
*/
protected function _getDefaultShareName()
{
return _("Notes");
}
/**
* Add any modifiers required to the share in order to mark it as default.
*
* @param Horde_Share_Object $share The new default share.
*/
protected function _prepareDefaultShare($share)
{
$share->set('default', true);
}
} mnemo-4.2.9/lib/.htaccess 0000664 0001750 0001750 00000000174 12654116457 013326 0 ustar jan jan
Require all denied
Deny from all
mnemo-4.2.9/lib/Api.php 0000664 0001750 0001750 00000055126 12654116457 012761 0 ustar jan jan '%application%/view.php?memo=|memo|&memolist=|memolist|&uid=|uid|'
);
/**
* Removes user data.
*
* @deprecated Use Horde's removeUserData API call instead.
*
* @param string $user Name of user to remove data for.
*
* @throws Mnemo_Exception
*/
public function removeUserData($user)
{
try {
$GLOBALS['registry']->removeUserData($user, 'mnemo');
} catch (Horde_Exception $e) {
throw new Mnemo_Exception($e);
}
}
/**
* @param boolean $owneronly Only return notepads that this user owns?
* Defaults to false.
* @param integer $permission The permission to filter notepads by.
*
* @return array The notepads.
*/
public function listNotepads($owneronly, $permission)
{
return Mnemo::listNotepads($owneronly, $permission);
}
/**
* Returns an array of UIDs for all notes that the current user is authorized
* to see.
*
* @param array|string $notepads The notepad(s) to list notes from.
*
* @return array An array of UIDs for all notes the user can access.
* @throws Mnemo_Exception
* @throws Horde_Exception_PermissionDenied
*/
public function listUids($notepads = null)
{
global $conf;
if (!isset($conf['storage']['driver'])) {
throw new RuntimeException('Not configured');
}
// Make sure we have a valid notepad.
if (empty($notepads)) {
$notepads = Mnemo::getSyncNotepads();
} else {
if (!is_array($notepads)) {
$notepads = array($notepads);
}
foreach ($notepads as $notepad) {
if (!Mnemo::hasPermission($notepad, Horde_Perms::READ)) {
throw new Horde_Exception_PermissionDenied();
}
}
}
// Set notepad for listMemos.
$GLOBALS['display_notepads'] = $notepads;
$memos = Mnemo::listMemos();
$uids = array();
foreach ($memos as $memo) {
$uids[] = $memo['uid'];
}
return $uids;
}
/**
* Method for obtaining all server changes between two timestamps. Basically
* a wrapper around listBy(), but returns an array containing all adds,
* edits and deletions.
*
* @param integer $start The starting timestamp
* @param integer $end The ending timestamp.
* @param boolean $isModSeq If true, $timestamp and $end are
* modification sequences and not
* timestamps. @since 4.1.1
* @param string|array $notepads The sources to check. @since 4.2.0
*
* @return array An hash with 'add', 'modify' and 'delete' arrays.
*/
public function getChanges($start, $end, $isModSeq = false, $notepads = null)
{
return array('add' => $this->listBy('add', $start, $notepads, $end, $isModSeq),
'modify' => $this->listBy('modify', $start, $notepads, $end, $isModSeq),
'delete' => $this->listBy('delete', $start, $notepads, $end, $isModSeq));
}
/**
* Return all changes occuring between the specified modification
* sequences.
*
* @param integer $start The starting modseq.
* @param integer $end The ending modseq.
* @param string|array $notepads The sources to check. @since 4.2.0
*
* @return array The changes @see getChanges()
* @since 4.1.1
*/
public function getChangesByModSeq($start, $end, $notepads = null)
{
return $this->getChanges($start, $end, true, $notepads);
}
/**
* Returns an array of UIDs for notes that have had $action happen since
* $timestamp.
*
* @param string $action The action to check for - add, modify, or delete.
* @param integer $timestamp The time to start the search.
* @param string $notepad The notepad to search in.
* @param integer $end The optional ending timestamp.
* @param boolean $isModSeq If true, $timestamp and $end are modification
* sequences and not timestamps. @since 4.1.1
*
* @return array An array of UIDs matching the action and time criteria.
*/
public function listBy($action, $timestamp, $notepad = null, $end = null, $isModSeq = false)
{
/* Make sure we have a valid notepad. */
if (empty($notepad)) {
$notepads = Mnemo::getSyncNotepads();
$results = array();
foreach ($notepads as $notepad) {
$results = array_merge($results, $this->listBy($action, $timestamp, $notepad, $end, $isModSeq));
}
return $results;
}
$filter = array(array('op' => '=', 'field' => 'action', 'value' => $action));
if (!empty($end) && !$isModSeq) {
$filter[] = array('op' => '<', 'field' => 'ts', 'value' => $end);
}
$history = $GLOBALS['injector']->getInstance('Horde_History');
if (!$isModSeq) {
$histories = $history->getByTimestamp('>', $timestamp, $filter, 'mnemo:' . $notepad);
} else {
$histories = $history->getByModSeq($timestamp, $end, $filter, 'mnemo:' . $notepad);
}
// Strip leading mnemo:username:.
return preg_replace('/^([^:]*:){2}/', '', array_keys($histories));
}
/**
* Returns the timestamp of an operation for a given uid an action.
*
* @param string $uid The uid to look for.
* @param string $action The action to check for - add, modify, or delete.
* @param string $notepad The notepad to search in.
* @param boolean $modSeq Request a modification sequence instead of a
* timestamp. @since 4.1.1
*
* @return integer The timestamp or modseq for this action.
* @throws Horde_Exception_PermissionDenied
*/
public function getActionTimestamp($uid, $action, $notepad = null, $modSeq = false)
{
/* Make sure we have a valid notepad. */
if (empty($notepad)) {
$notepad = Mnemo::getDefaultNotepad();
}
if (!array_key_exists($notepad, Mnemo::listNotepads(false, Horde_Perms::READ))) {
throw new Horde_Exception_PermissionDenied();
}
$history = $GLOBALS['injector']->getInstance('Horde_History');
if (!$modSeq) {
return $history->getActionTimestamp('mnemo:' . $notepad . ':' . $uid, $action);
} else {
return $history->getActionModSeq('mnemo:' . $notepad . ':' . $uid, $action);
}
}
/**
* Return the largest modification sequence from the history backend.
*
* @param string $id The notepad id to get the MODSEQ for. If null, the
* highest MODSEQ across all notepads is returned.
* @since 4.2.0
*
* @return integer The modseq.
* @since 4.1.1
*/
public function getHighestModSeq($id = null)
{
$parent = 'mnemo';
if (!empty($id)) {
$parent .= ':' . $id;
}
return $GLOBALS['injector']->getInstance('Horde_History')->getHighestModSeq($parent);
}
/**
* Import a memo represented in the specified contentType.
*
* @param string $content The content of the memo.
* @param string $contentType What format is the data in? Currently supports:
* text/plain
* text/x-vnote
* activesync
* @param string $notepad (optional) The notepad to save the memo on.
*
* @return string The new UID, or false on failure.
* @throws Mnemo_Exception
* @throws Horde_Exception_PermissionDenied
*/
public function import($content, $contentType, $notepad = null)
{
global $prefs;
/* Make sure we have a valid notepad and permissions to edit
* it. */
if (empty($notepad)) {
$notepad = Mnemo::getDefaultNotepad(Horde_Perms::EDIT);
}
if (!array_key_exists($notepad, Mnemo::listNotepads(false, Horde_Perms::EDIT))) {
throw new Horde_Exception_PermissionDenied();
}
/* Create a Mnemo_Driver instance. */
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
switch ($contentType) {
case 'text/plain':
$noteId = $storage->add($storage->getMemoDescription($content), $content);
break;
case 'text/x-vnote':
if (!($content instanceof Horde_Icalendar_Vnote)) {
$iCal = new Horde_Icalendar();
if (!$iCal->parsevCalendar($content)) {
throw new Mnemo_Exception(_("There was an error importing the iCalendar data."));
}
$components = $iCal->getComponents();
switch (count($components)) {
case 0:
throw new Mnemo_Exception(_("No iCalendar data was found."));
case 1:
$content = $components[0];
break;
default:
$ids = array();
foreach ($components as $content) {
if ($content instanceof Horde_Icalendar_Vnote) {
$note = $storage->fromiCalendar($content);
$noteId = $storage->add(
$note['desc'], $note['body'],
!empty($note['tags']) ? $note['tags'] : '');
$ids[] = $noteId;
}
}
return $ids;
}
}
$note = $storage->fromiCalendar($content);
$noteId = $storage->add(
$note['desc'], $note['body'],
!empty($note['tags']) ? $note['tags'] : '');
break;
case 'activesync':
// We only support plaintext
if ($content->body->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
$body = Horde_Text_Filter::filter($content->body->data, 'Html2text');
} else {
$body = $content->body->data;
}
$noteId = $storage->add(Horde_String::substr($content->subject, 0, 255), $body, $content->categories);
break;
default:
throw new Mnemo_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType));
}
$note = $storage->get($noteId);
return $note['uid'];
}
/**
* Export a memo, identified by UID, in the requested contentType.
*
* @param string $uid Identify the memo to export.
* @param string $contentType What format should the data be in?
* A string with one of:
*
* 'text/plain'
* 'text/x-vnote'
* 'activesync'
*
* @param array $options Any additional options to be passed to the
* exporter.
*
* @return mixed The requested data
* @throws Mnemo_Exception
* @throws Horde_Exception_PermissionDenied
*/
public function export($uid, $contentType, array $options = array())
{
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
$memo = $storage->getByUID($uid);
if (!array_key_exists($memo['memolist_id'], Mnemo::listNotepads(false, Horde_Perms::READ))) {
throw new Horde_Exception_PermissionDenied();
}
switch ($contentType) {
case 'text/plain':
return $memo['body'];
case 'text/x-vnote':
// Create the new iCalendar container.
$iCal = new Horde_Icalendar('1.1');
$iCal->setAttribute('VERSION', '1.1');
$iCal->setAttribute('PRODID', '-//The Horde Project//Mnemo ' . $GLOBALS['registry']->getVersion() . '//EN');
$iCal->setAttribute('METHOD', 'PUBLISH');
// Create a new vNote.
$vNote = $storage->toiCalendar($memo, $iCal);
return $vNote->exportvCalendar();
case 'activesync':
return $storage->toASNote($memo, $options);
}
throw new Mnemo_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType));
}
/**
* Delete a memo identified by UID.
*
* @param string | array $uid Identify the note to delete, either a
* single UID or an array.
* @throws Horde_Exception_PermissionDenied
*/
public function delete($uid)
{
// Handle an arrray of UIDs for convenience of deleting multiple
// notes at once.
if (is_array($uid)) {
foreach ($uid as $u) {
$result = $this->delete($u);
}
return;
}
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
$memo = $storage->getByUID($uid);
if (!$GLOBALS['registry']->isAdmin() &&
!array_key_exists($memo['memolist_id'], Mnemo::listNotepads(false, Horde_Perms::DELETE))) {
throw new Horde_Exception_PermissionDenied();
}
$storage->delete($memo['memo_id']);
}
/**
* Replace the memo identified by UID with the content represented in
* the specified contentType.
*
* @param string $uid Idenfity the memo to replace.
* @param string $content The content of the memo.
* @param string $contentType What format is the data in? Currently supports:
* text/plain
* text/x-vnote
* activesync
* @throws Mnemo_Exception
* @throws Horde_Exception_PermissionDenied
*/
public function replace($uid, $content, $contentType)
{
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create();
$memo = $storage->getByUID($uid);
if (!array_key_exists($memo['memolist_id'], Mnemo::listNotepads(false, Horde_Perms::EDIT))) {
throw new Horde_Exception_PermissionDenied();
}
switch ($contentType) {
case 'text/plain':
$storage->modify($memo['memo_id'], $storage->getMemoDescription($content), $content, null);
break;
case 'text/x-vnote':
if (!($content instanceof Horde_Icalendar_Vnote)) {
$iCal = new Horde_Icalendar();
if (!$iCal->parsevCalendar($content)) {
throw new Mnemo_Exception(_("There was an error importing the iCalendar data."));
}
$components = $iCal->getComponents();
switch (count($components)) {
case 0:
throw new Mnemo_Exception(_("No iCalendar data was found."));
case 1:
$content = $components[0];
break;
default:
throw new Mnemo_Exception(_("Multiple iCalendar components found; only one vNote is supported."));
}
}
$note = $storage->fromiCalendar($content);
$storage->modify($memo['memo_id'],
$note['desc'],
$note['body'],
!empty($note['tags']) ? $note['tags'] : '');
break;
case 'activesync':
// We only support plaintext
if ($content->body->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
$body = Horde_Text_Filter::filter($content->body->data, 'Html2text');
} else {
$body = $content->body->data;
}
$storage->modify($memo['memo_id'], Horde_String::substr($content->subject, 0, 255), $body, $content->categories);
break;
default:
throw new Mnemo_Exception(sprintf(_("Unsupported Content-Type: %s"),$contentType));
}
}
/**
* Returns a list of available sources.
*
* @param boolean $writeable If true, limits to writeable sources.
* @param boolean $sync_only Only include synchable notepads.
*
* @return array An array of the available sources. Keys are source IDs,
* values are source titles.
* @since 4.2.0
*/
public function sources($writeable = false, $sync_only = false)
{
$out = array();
foreach (Mnemo::listNotepads(false, $writeable ? Horde_Perms::EDIT : Horde_Perms::READ) as $key => $val) {
$out[$key] = $val->get('name');
}
if ($sync_only) {
$syncable = Mnemo::getSyncNotepads();
$out = array_intersect_key($out, array_flip($syncable));
}
return $out;
}
/**
* Retrieve the UID for the current user's default notepad.
*
* @return string UID.
* @since 4.2.0
*/
public function getDefaultShare()
{
return Mnemo::getDefaultNotepad(Horde_Perms::EDIT);
}
/**
* Create a new notepad.
*
* @param string $name The notepad display name.
* @param array $params Any additional parameters needed.
* - synchronize: (boolean) If true, add notepad to the list of
* notepads to syncronize.
* DEFAULT: false (do not add to the list).
* @since 4.2.1
*
* @return string The new notepad's id.
* @since 4.2.0
*/
public function addNotepad($name, array $params = array())
{
if ($GLOBALS['prefs']->isLocked('default_notepad')) {
throw new Horde_Exception_PermissionDenied();
}
$notepad = $GLOBALS['mnemo_shares']->newShare(
$GLOBALS['registry']->getAuth(),
strval(new Horde_Support_Uuid()),
$name);
$name = $notepad->getName();
if (!empty($params['synchronize'])) {
$sync = @unserialize($prefs->getValue('sync_notepads'));
$sync[] = $name;
$prefs->setValue('sync_notepads', serialize($sync));
}
return $name;
}
/**
* Delete notepad.
*
* @param string $id The notepad id.
* @since 4.2.0
*/
public function deleteNotepad($id)
{
// Delete the notepad.
$storage = $GLOBALS['injector']
->getInstance('Mnemo_Factory_Driver')
->create($id);
$storage->deleteAll();
$share = $GLOBALS['mnemo_shares']->getShare($id);
$GLOBALS['mnemo_shares']->removeShare($share);
}
/**
* Update a notepad's title and/or description.
*
* @param string $id The notepad id
* @param array $info The data to change:
* - name: The display name.
* - desc: The description.
*
* @since 4.2.0
*/
public function updateNotepad($id, array $info)
{
$notepad = $GLOBALS['mnemo_shares']->getShare($id);
if (!empty($info['name'])) {
$notepad->set('name', $info['name']);
}
if (!empty($info['desc'])) {
$notepad->set('desc', $info['desc']);
}
$notepad->save();
}
/**
* Retrieve the list of used tag_names, tag_ids and the total number
* of resources that are linked to that tag.
*
* @param array $tags An optional array of tag_ids. If omitted, all tags
* will be included.
*
* @return array An array containing tag_name, and total
*/
public function listTagInfo($tags = null, $user = null)
{
return $GLOBALS['injector']->getInstance('Mnemo_Tagger')
->getTagInfo($tags, 500, null, $user);
}
/**
* SearchTags API:
* Returns an application-agnostic array (useful for when doing a tag search
* across multiple applications)
*
* The 'raw' results array can be returned instead by setting $raw = true.
*
* @param array $names An array of tag_names to search for.
* @param integer $max The maximum number of resources to return.
* @param integer $from The number of the resource to start with.
* @param string $resource_type The resource type [bookmark, '']
* @param string $user Restrict results to resources owned by $user.
* @param boolean $raw Return the raw data?
*
* @return array An array of results:
*
* 'title' - The title for this resource.
* 'desc' - A terse description of this resource.
* 'view_url' - The URL to view this resource.
* 'app' - The Horde application this resource belongs to.
* 'icon' - URL to an image.
*
*/
public function searchTags($names, $max = 10, $from = 0,
$resource_type = '', $user = null, $raw = false)
{
// TODO: $max, $from, $resource_type not honored
global $injector, $registry;
$results = $injector
->getInstance('Mnemo_Tagger')
->search(
$names,
array('user' => $user));
// Check for error or if we requested the raw data array.
if ($raw) {
return $results;
}
$return = array();
$redirectUrl = Horde::url('memo.php');
foreach ($results as $memo_id) {
try {
$memo = $injector->getInstance('Mnemo_Factory_Driver')
->create(null)
->getByUID($memo_id);
$return[] = array(
'title' => $memo['desc'],
'desc' => '',
'view_url' => $redirectUrl->copy()->add(array('memo' => $memo['memo_id'], 'memolist' => $memo['memolist_id'])),
'app' => 'mnemo'
);
} catch (Exception $e) {
}
}
return $return;
}
}
mnemo-4.2.9/lib/Application.php 0000664 0001750 0001750 00000023125 12654116457 014505 0 ustar jan jan true,
'modseq' => true,
);
/**
*/
public $version = 'H5 (4.2.9)';
/**
* Global variables defined:
* $mnemo_shares - TODO
*/
protected function _init()
{
/* For now, autoloading the Content_* classes depend on there being a
* registry entry for the 'content' application that contains at least
* the fileroot entry. */
$GLOBALS['injector']->getInstance('Horde_Autoloader')
->addClassPathMapper(
new Horde_Autoloader_ClassPathMapper_Prefix('/^Content_/', $GLOBALS['registry']->get('fileroot', 'content') . '/lib/'));
if (!class_exists('Content_Tagger')) {
throw new Horde_Exception(_("The Content_Tagger class could not be found. Make sure the Content application is installed."));
}
Mnemo::initialize();
}
/**
*/
public function perms()
{
return array(
'max_notes' => array(
'title' => _("Maximum Number of Notes"),
'type' => 'int'
)
);
}
/**
*/
public function menu($menu)
{
global $conf, $injector;
$menu->add(Horde::url('list.php'), _("_List Notes"), 'mnemo-list', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
/* Search. */
$menu->add(Horde::url('search.php'), _("_Search"), 'mnemo-search');
/* Import/Export */
if ($conf['menu']['import_export']) {
$menu->add(Horde::url('data.php'), _("_Import/Export"), 'horde-data');
}
}
/**
* Add additional items to the sidebar.
*
* @param Horde_View_Sidebar $sidebar The sidebar object.
*/
public function sidebar($sidebar)
{
$perms = $GLOBALS['injector']->getInstance('Horde_Core_Perms');
if (Mnemo::getDefaultNotepad(Horde_Perms::EDIT) &&
($perms->hasAppPermission('max_notes') === true ||
$perms->hasAppPermission('max_notes') > Mnemo::countMemos())) {
$sidebar->addNewButton(
_("_New Note"),
Horde::url('memo.php')->add('actionID', 'add_memo'));
}
$url = Horde::url('');
$edit = Horde::url('notepads/edit.php');
$user = $GLOBALS['registry']->getAuth();
$sidebar->containers['my'] = array(
'header' => array(
'id' => 'mnemo-toggle-my',
'label' => _("My Notepads"),
'collapsed' => false,
),
);
if (!$GLOBALS['prefs']->isLocked('default_notepad')) {
$sidebar->containers['my']['header']['add'] = array(
'url' => Horde::url('notepads/create.php'),
'label' => _("Create a new Notepad"),
);
}
$sidebar->containers['shared'] = array(
'header' => array(
'id' => 'mnemo-toggle-shared',
'label' => _("Shared Notepads"),
'collapsed' => true,
),
);
foreach (Mnemo::listNotepads() as $name => $notepad) {
$url->add(array(
'display_notepad' => $name,
'actionID' => in_array($name, $GLOBALS['display_notepads'])
? 'remove_displaylist'
: 'add_displaylist'
));
$row = array(
'selected' => in_array($name, $GLOBALS['display_notepads']),
'url' => $url,
'label' => Mnemo::getLabel($notepad),
'color' => $notepad->get('color') ?: '#dddddd',
'edit' => $edit->add('n', $notepad->getName()),
'type' => 'checkbox',
);
if ($notepad->get('owner') == $user) {
$sidebar->addRow($row, 'my');
} else {
$sidebar->addRow($row, 'shared');
}
}
}
/**
*/
public function hasPermission($permission, $allowed, $opts = array())
{
if (is_array($allowed)) {
switch ($permission) {
case 'max_notes':
$allowed = max($allowed);
break;
}
}
return $allowed;
}
/* Topbar method. */
/**
*/
public function topbarCreate(Horde_Tree_Renderer_Base $tree, $parent = null,
array $params = array())
{
global $registry;
$add = Horde::url('memo.php', true)->add('actionID', 'add_memo');
$tree->addNode(array(
'id' => $parent . '__new',
'parent' => $parent,
'label' => _("New Note"),
'expanded' => false,
'params' => array(
'icon' => Horde_Themes::img('add.png'),
'url' => $add
)
));
$user = $registry->getAuth();
foreach (Mnemo::listNotepads(false, Horde_Perms::SHOW) as $name => $notepad) {
if (!$notepad->hasPermission($user, Horde_Perms::EDIT)) {
continue;
}
$tree->addNode(array(
'id' => $parent . $name . '__new',
'parent' => $parent . '__new',
'label' => sprintf(_("in %s"), Mnemo::getLabel($notepad)),
'expanded' => false,
'params' => array(
'icon' => Horde_Themes::img('add.png'),
'url' => $add->copy()->add('memolist', $name)
)
));
}
$tree->addNode(array(
'id' => $parent . '__search',
'parent' => $parent,
'label' => _("Search"),
'expanded' => false,
'params' => array(
'icon' => Horde_Themes::img('search.png'),
'url' => Horde::url('search.php')
)
));
}
/**
*/
public function removeUserData($user)
{
$error = false;
$notepads = $GLOBALS['mnemo_shares']->listShares(
$user, array('attributes' => $user));
foreach ($notepads as $notepad => $share) {
$driver = $GLOBALS['injector']
->getInstance('Mnemo_Factory_Driver')
->create($notepad);
try {
$driver->deleteAll();
} catch (Mnemo_Exception $e) {
Horde::log($e, 'NOTICE');
$error = true;
}
try {
$GLOBALS['mnemo_shares']->removeShare($share);
} catch (Horde_Share_Exception $e) {
Horde::log($e, 'NOTICE');
$error = true;
}
}
// Get a list of all shares this user has perms to and remove the perms.
try {
$shares = $GLOBALS['mnemo_shares']->listShares($user);
foreach ($shares as $share) {
$share->removeUser($user);
}
} catch (Horde_Share_Exception $e) {
Horde::log($e, 'NOTICE');
$error = true;
}
if ($error) {
throw new Mnemo_Exception(sprintf(_("There was an error removing notes for %s. Details have been logged."), $user));
}
}
/* Download data. */
/**
* @throws Mnemo_Exception
*/
public function download(Horde_Variables $vars)
{
global $injector, $registry;
switch ($vars->actionID) {
case 'export':
/* Get the full, sorted memo list. */
$notes = Mnemo::listMemos();
switch ($vars->exportID) {
case Horde_Data::EXPORT_CSV:
$data = array();
foreach ($notes as $note) {
unset(
$note['desc'],
$note['memo_id'],
$note['memolist_id'],
$nore['uid']
);
$note['tags'] = implode(',', $note['tags']);
if ($note['body'] instanceof Mnemo_Exception) {
$note['body'] = $note['body']->getMessage();
}
$data[] = $note;
}
$injector->getInstance('Horde_Core_Factory_Data')
->create('Csv',
array('cleanup' => array($this, 'cleanupData')))
->exportFile(_("notes.csv"), $data, true);
exit;
}
}
}
/**
*/
public function cleanupData()
{
$GLOBALS['import_step'] = 1;
return Horde_Data::IMPORT_FILE;
}
}
mnemo-4.2.9/lib/Driver.php 0000664 0001750 0001750 00000041354 12654116457 013501 0 ustar jan jan
* @author Michael J. Rubinsky
* @package Mnemo
*/
abstract class Mnemo_Driver
{
/**
* Array holding the current memo list. Each array entry is a hash
* describing a memo. The array is indexed numerically by memo ID.
*
* @var array
*/
protected $_memos = array();
/**
* String containing the current notepad name.
*
* @var string
*/
protected $_notepad = '';
/**
* Crypting processor.
*
* @var Horde_Crypt_pgp
*/
protected $_pgp;
/**
* Retrieves all of the notes of the current notepad from the backend.
*
* @thows Mnemo_Exception
*/
abstract public function retrieve();
/**
* Lists memos based on the given criteria. All memos will be
* returned by default.
*
* @return array Returns a list of the requested memos.
*/
public function listMemos()
{
return $this->_memos;
}
/**
* Update the description (short summary) of a memo.
*
* @param integer $memo_id The memo to update.
*/
public function getMemoDescription($body)
{
if (!strstr($body, "\n") && Horde_String::length($body) <= 64) {
return trim($body);
}
$lines = explode("\n", $body);
if (!is_array($lines)) {
return trim(Horde_String::substr($body, 0, 64));
}
// Move to a line with more than spaces.
$i = 0;
while (isset($lines[$i]) && !preg_match('|[^\s]|', $lines[$i])) {
$i++;
}
if (Horde_String::length($lines[$i]) <= 64) {
return trim($lines[$i]);
} else {
return trim(Horde_String::substr($lines[$i], 0, 64));
}
}
/**
* Retrieves one note from the backend.
*
* @param string $noteId The ID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
abstract public function get($noteId, $passphrase = null);
/**
* Retrieves one note from the backend by UID.
*
* @param string $uid The UID of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The array of note attributes.
* @throws Mnemo_Exception
* @throws Horde_Exception_NotFound
*/
abstract public function getByUID($uid, $passphrase = null);
/**
* Adds a note to the backend storage.
*
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
* @param string $passphrase The passphrase to encrypt the note with.
*
* @return string The ID of the new note.
* @throws Mnemo_Exception
*/
public function add($desc, $body, $tags = '', $passphrase = null)
{
$noteId = $this->_generateId();
if ($passphrase) {
$body = $this->_encrypt($body, $passphrase);
Mnemo::storePassphrase($noteId, $passphrase);
}
$uid = $this->_add($noteId, $desc, $body, $tags);
// Add tags.
$GLOBALS['injector']->getInstance('Mnemo_Tagger')
->tag($uid, $tags, $GLOBALS['registry']->getAuth(), 'note');
// Log the creation of this item in the history log.
try {
$GLOBALS['injector']->getInstance('Horde_History')
->log('mnemo:' . $this->_notepad . ':' . $uid,
array('action' => 'add'), true);
} catch (Horde_Exception $e) {
}
return $noteId;
}
/**
* Adds a note to the backend storage.
*
* @param string $noteId The ID of the new note.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return string The unique ID of the new note.
* @throws Mnemo_Exception
*/
abstract protected function _add($noteId, $desc, $body, $tags);
/**
* Modifies an existing note.
*
* @param string $noteId The note to modify.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
* @param string $passphrase The passphrase to encrypt the note with.
*
* @throws Mnemo_Exception
*/
public function modify($noteId, $desc, $body, $tags = '',
$passphrase = null)
{
if ($passphrase) {
$body = $this->_encrypt($body, $passphrase);
Mnemo::storePassphrase($noteId, $passphrase);
}
$uid = $this->_modify($noteId, $desc, $body, $tags);
// Update tags.
$GLOBALS['injector']->getInstance('Mnemo_Tagger')
->replaceTags($uid, $tags, $GLOBALS['registry']->getAuth(), 'note');
// Log the modification of this item in the history log.
if ($uid) {
try {
$GLOBALS['injector']->getInstance('Horde_History')
->log('mnemo:' . $this->_notepad . ':' . $uid,
array('action' => 'modify'), true);
} catch (Horde_Exception $e) {
}
}
}
/**
* Modifies an existing note.
*
* @param string $noteId The note to modify.
* @param string $desc The first line of the note.
* @param string $body The whole note body.
* @param string $tags The tags of the note.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
abstract protected function _modify($noteId, $desc, $body, $tags);
/**
* Moves a note to a new notepad.
*
* @param string $noteId The note to move.
* @param string $newNotepad The new notepad.
*
* @throws Mnemo_Exception
*/
public function move($noteId, $newNotepad)
{
$uid = $this->_move($noteId, $newNotepad);
// Log the moving of this item in the history log.
if ($uid) {
try {
$history = $GLOBALS['injector']->getInstance('Horde_History');
$history->log('mnemo:' . $this->_notepad . ':' . $uid,
array('action' => 'delete'), true);
$history->log('mnemo:' . $newNotepad . ':' . $uid,
array('action' => 'add'), true);
} catch (Horde_Exception $e) {
}
}
}
/**
* Moves a note to a new notepad.
*
* @param string $noteId The note to move.
* @param string $newNotepad The new notepad.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
abstract protected function _move($noteId, $newNotepad);
/**
* Deletes a note permanently.
*
* @param string $noteId The note to delete.
*
* @throws Mnemo_Exception
*/
public function delete($noteId)
{
$uid = $this->_delete($noteId);
// Log the deletion of this item in the history log.
if ($uid) {
try {
$GLOBALS['injector']->getInstance('Horde_History')
->log('mnemo:' . $this->_notepad . ':' . $uid,
array('action' => 'delete'), true);
} catch (Horde_Exception $e) {
}
// Remove tags
$GLOBALS['injector']->getInstance('Mnemo_Tagger')
->replaceTags($uid, array(), $GLOBALS['registry']->getAuth(), 'note');
/* Tell content we removed the object */
$GLOBALS['injector']->getInstance('Content_Objects_Manager')
->delete(array($uid), 'note');
}
}
/**
* Deletes a note permanently.
*
* @param array $note The note to delete.
*
* @return string The note's UID.
* @throws Mnemo_Exception
*/
abstract protected function _delete($noteId);
/**
* Deletes all notes from the current notepad.
*
* @throws Mnemo_Exception
*/
public function deleteAll()
{
$uids = $this->_deleteAll();
// Update History.
$history = $GLOBALS['injector']->getInstance('Horde_History');
try {
foreach ($uids as $uid) {
$history->log(
'mnemo:' . $this->_notepad . ':' . $uid,
array('action' => 'delete'),
true);
$GLOBALS['injector']->getInstance('Mnemo_Tagger')
->replaceTags($uid, array(), $GLOBALS['registry']->getAuth(), 'note');
/* Tell content we removed the object */
$GLOBALS['injector']->getInstance('Content_Objects_Manager')
->delete(array($uid), 'note');
}
} catch (Horde_Exception $e) {
}
}
/**
* Deletes all notes from the current notepad.
*
* @return array An array of uids that have been removed.
* @throws Mnemo_Exception
*/
abstract protected function _deleteAll();
/**
* Loads the PGP encryption driver.
*
* @TODO: Inject *into* driver from the factory binder
*/
protected function _loadPGP()
{
if (empty($GLOBALS['conf']['gnupg']['path'])) {
throw new Mnemo_Exception(_("Encryption support has not been configured, please contact your administrator."));
}
$this->_pgp = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Crypt')->create('pgp', array(
'program' => $GLOBALS['conf']['gnupg']['path']
));
}
/**
* Encrypts a note.
*
* @param string $note The note text.
* @param string $passphrase The passphrase to encrypt the note with.
*
* @return string The encrypted text.
*/
protected function _encrypt($note, $passphrase)
{
$this->_loadPGP();
return $this->_pgp->encrypt($note, array('type' => 'message', 'symmetric' => true, 'passphrase' => $passphrase));
}
/**
* Decrypts a note.
*
* @param string $note The encrypted note text.
* @param string $passphrase The passphrase to decrypt the note with.
*
* @return string The decrypted text.
* @throws Mnemo_Exception
*/
protected function _decrypt($note, $passphrase)
{
$this->_loadPGP();
try {
return $this->_pgp->decrypt($note, array('type' => 'message', 'passphrase' => $passphrase));
} catch (Horde_Crypt_Exception $e) {
throw new Mnemo_Exception($e->getMessage(), Mnemo::ERR_DECRYPT);
}
}
/**
* Returns whether note encryption is supported.
*
* Checks if PGP support could be loaded, if it supports symmetric
* encryption, and if we have a secure connection.
*
* @return boolean Whether encryption is suppoted.
*/
public function encryptionSupported()
{
try {
$this->_loadPGP();
} catch (Mnemo_Exception $e) {
}
return (is_callable(array($this->_pgp, 'encryptedSymmetrically')) &&
Horde::isConnectionSecure());
}
/**
* Create an AS memo from this task
*
* @param array $memo A memo array.
* @param array $options
*
* @return Horde_ActiveSync_Message_Note
*/
public function toASNote($memo, $options = array())
{
$message = new Horde_ActiveSync_Message_Note(array(
'protocolversion' => $options['protocolversion']));
$message->subject = $memo['desc'];
$bp = $options['bodyprefs'];
$body = new Horde_ActiveSync_Message_AirSyncBaseBody();
// When the note is encrypted, we won't have the passphrase so the
// body will be a Mnemo_Exception.
if ($memo['body'] instanceof Mnemo_Exception) {
$memo['body'] = $memo['body']->getMessage();
}
if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML])) {
$body->type = Horde_ActiveSync::BODYPREF_TYPE_HTML;
$memo['body'] = Horde_Text_Filter::filter($memo['body'], 'Text2html', array('parselevel' => Horde_Text_Filter_Text2html::MICRO));
if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) &&
Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']) {
$body->data = Horde_String::substr($memo['body'], $bp[Horde_ActiveSync::BODYPREF_TYPE_HTML]['truncationsize']);
$body->truncated = 1;
} else {
$body->data = $memo['body'];
}
} else {
$body->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN;
if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) &&
Horde_String::length($memo['body']) > $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) {
$body->data = Horde_String::substr($memo['body'], 0, $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']);
$body->truncated = 1;
} else {
$body->data = $memo['body'];
}
}
$body->estimateddatasize = Horde_String::length($memo['body']);
$message->body = $body;
if (!empty($memo['tags'])) {
$message->categories = $memo['tags'];
}
$history = $GLOBALS['injector']->getInstance('Horde_History');
$last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'modify');
if (empty($last)) {
$last = $history->getActionTimeStamp('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid'], 'add');
}
$message->lastmodified = new Horde_Date($last);
return $message;
}
/**
* Export this memo in iCalendar format.
*
* @param array memo The memo (hash array) to export
* @param Horde_Icalendar A Horde_Icalendar object that acts as container.
*
* @return Horde_Icalendar_Vnote object for this event.
*/
public function toiCalendar($memo, $calendar)
{
global $prefs;
$vnote = Horde_Icalendar::newComponent('vnote', $calendar);
$vnote->setAttribute('UID', $memo['uid']);
$vnote->setAttribute('BODY', $memo['body']);
$vnote->setAttribute('SUMMARY', $memo['desc']);
if (!empty($memo['tags'])) {
$vnote->setAttribute('CATEGORIES', implode(', ', $memo['tags']));
}
/* Get the note's history. */
$history = $GLOBALS['injector']->getInstance('Horde_History');
$log = $history->getHistory('mnemo:' . $memo['memolist_id'] . ':' . $memo['uid']);
if ($log) {
foreach ($log as $entry) {
switch ($entry['action']) {
case 'add':
$created = $entry['ts'];
break;
case 'modify':
$modified = $entry['ts'];
break;
}
}
}
if (!empty($created)) {
$vnote->setAttribute('DCREATED', $created);
}
if (!empty($modified)) {
$vnote->setAttribute('LAST-MODIFIED', $modified);
}
return $vnote;
}
/**
* Create a memo (hash array) from a Horde_Icalendar_Vnote object.
*
* @param Horde_Icalendar_Vnote $vnote The iCalendar data to update from.
*
* @return array Memo (hash array) created from the vNote.
*/
public function fromiCalendar(Horde_Icalendar_Vnote $vNote)
{
$memo = array();
try {
$body = $vNote->getAttribute('BODY');
} catch (Horde_Icalendar_Exception $e) {
}
if (!is_array($body)) {
$memo['body'] = $body;
} else {
$memo['body'] = '';
}
$memo['desc'] = $this->getMemoDescription($memo['body']);
try {
$cat = $vNote->getAttribute('CATEGORIES');
if (!is_array($cat)) {
$memo['tags'] = $cat;
}
} catch (Horde_Icalendar_Exception $e) {
}
return $memo;
}
/**
* Generates a local note ID.
*
* @return string A new note ID.
*/
abstract protected function _generateId();
}
mnemo-4.2.9/lib/Exception.php 0000664 0001750 0001750 00000000604 12654116457 014175 0 ustar jan jan
* @package Mnemo
*/
class Mnemo_Exception extends Horde_Exception_Wrapped
{
}
mnemo-4.2.9/lib/Mnemo.php 0000664 0001750 0001750 00000043413 12654116457 013317 0 ustar jan jan
* @package Mnemo
*/
class Mnemo
{
/**
* Sort by memo description.
*/
const SORT_DESC = 0;
/**
* Sort by notepad.
*/
const SORT_NOTEPAD = 2;
/**
* Sort by moddate
*/
const SORT_MOD_DATE = 3;
/**
* Sort in ascending order.
*/
const SORT_ASCEND = 0;
/**
* Sort in descending order.
*/
const SORT_DESCEND = 1;
/**
* No passphrase provided.
*/
const ERR_NO_PASSPHRASE = 100;
/**
* Decrypting failed
*/
const ERR_DECRYPT = 101;
/**
* Retrieves the current user's note list from storage. This function will
* also sort the resulting list, if requested.
*
* @param constant $sortby The field by which to sort. (self::SORT_DESC,
* self::SORT_NOTEPAD, self::SORT_MOD_DATE)
* @param constant $sortdir The direction by which to sort.
* (self::SORT_ASC, self::SORT_DESC)
*
* @return array A list of the requested notes.
*
* @see Mnemo_Driver::listMemos()
*/
public static function listMemos($sortby = self::SORT_DESC,
$sortdir = self::SORT_ASCEND)
{
global $conf, $display_notepads;
$memos = array();
/* Sort the memo list. */
$sort_functions = array(
self::SORT_DESC => 'ByDesc',
self::SORT_NOTEPAD => 'ByNotepad',
self::SORT_MOD_DATE => 'ByModDate'
);
foreach ($display_notepads as $notepad) {
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
try {
$storage->retrieve();
} catch (Mnemo_Exception $e) {
$GLOBALS['notification']->push($e, 'horde.error');
}
$newmemos = $storage->listMemos();
$memos = array_merge($memos, $newmemos);
}
// Sort the array if we have a sort function defined
if (isset($sort_functions[$sortby])) {
$prefix = ($sortdir == self::SORT_DESCEND) ? '_rsort' : '_sort';
uasort($memos, array('Mnemo', $prefix . $sort_functions[$sortby]));
}
return $memos;
}
/**
* Returns the number of notes in notepads that the current user owns.
*
* @return integer The number of notes that the user owns.
*/
public static function countMemos()
{
static $count;
if (isset($count)) {
return $count;
}
$notepads = self::listNotepads(true, Horde_Perms::ALL);
$count = 0;
foreach (array_keys($notepads) as $notepad) {
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
$storage->retrieve();
$count += count($storage->listMemos());
}
return $count;
}
/**
* Retrieves a specific note from storage.
*
* @param string $notepad The notepad to retrieve the note from.
* @param string $noteId The Id of the note to retrieve.
* @param string $passphrase A passphrase with which this note was
* supposed to be encrypted.
*
* @return array The note.
*/
public static function getMemo($notepad, $noteId, $passphrase = null)
{
$storage = $GLOBALS['injector']->getInstance('Mnemo_Factory_Driver')->create($notepad);
return $storage->get($noteId, $passphrase);
}
/**
* Get preview text for a note (the first 20 lines or so).
*
* @param array $note The note array
*
* @return string A few lines of the note for previews or tooltips.
*/
public static function getNotePreview($note)
{
$body = $note['body'];
if ($body instanceof Mnemo_Exception) {
$body = $body->getMessage();
}
$lines = explode("\n", wordwrap($body));
return implode("\n", array_splice($lines, 0, 20));
}
/**
* Lists all notepads a user has access to.
*
* This method takes the $conf['share']['hidden'] setting into account. If
* this setting is enabled, even if requesting permissions different than
* SHOW, it will only return calendars that the user owns or has SHOW
* permissions for. For checking individual calendar's permissions, use
* hasPermission() instead.
*
* @param boolean $owneronly Only return memo lists that this user owns?
* Defaults to false.
* @param integer $permission The permission to filter notepads by.
*
* @return array The memo lists.
*/
public static function listNotepads($owneronly = false,
$permission = Horde_Perms::SHOW)
{
if ($owneronly && !$GLOBALS['registry']->getAuth()) {
return array();
}
if ($owneronly || empty($GLOBALS['conf']['share']['hidden'])) {
try {
$notepads = $GLOBALS['mnemo_shares']->listShares(
$GLOBALS['registry']->getAuth(),
array('perm' => $permission,
'attributes' => $owneronly ? $GLOBALS['registry']->getAuth() : null,
'sort_by' => 'name'));
} catch (Horde_Share_Exception $e) {
Horde::log($e->getMessage(), 'ERR');
return array();
}
} else {
try {
$notepads = $GLOBALS['mnemo_shares']->listShares(
$GLOBALS['registry']->getAuth(),
array('perm' => $permission,
'attributes' => $GLOBALS['registry']->getAuth(),
'sort_by' => 'name'));
} catch (Horde_Share_Exception $e) {
Horde::log($e);
return array();
}
$display_notepads = @unserialize($GLOBALS['prefs']->getValue('display_notepads'));
if (is_array($display_notepads)) {
foreach ($display_notepads as $id) {
try {
$notepad = $GLOBALS['mnemo_shares']->getShare($id);
if ($notepad->hasPermission($GLOBALS['registry']->getAuth(), $permission)) {
$notepads[$id] = $notepad;
}
} catch (Horde_Exception_NotFound $e) {
} catch (Horde_Share_Exception $e) {
Horde::log($e);
return array();
}
}
}
}
return $notepads;
}
/**
* Returns the default notepad for the current user at the specified
* permissions level.
*
* @param integer $permission Horde_Perms constant for permission level
* required.
*
* @return string The notepad identifier, or null if none.
*/
public static function getDefaultNotepad($permission = Horde_Perms::SHOW)
{
$notepads = self::listNotepads(false, $permission);
$default_notepad = $GLOBALS['prefs']->getValue('default_notepad');
if (isset($notepads[$default_notepad])) {
return $default_notepad;
}
$default_notepad = $GLOBALS['injector']
->getInstance('Mnemo_Factory_Notepads')
->create()
->getDefaultShare();
if (!isset($notepads[$default_notepad])) {
reset($notepads);
$default_notepad = key($notepads);
}
$GLOBALS['prefs']->setValue('default_notepad', $default_notepad);
return $default_notepad;
}
/**
* Returns the label to be used for a notepad.
*
* Attaches the owner name of shared notepads if necessary.
*
* @param Horde_Share_Object A notepad.
*
* @return string The notepad's label.
*/
public static function getLabel($notepad)
{
$label = $notepad->get('name');
if ($notepad->get('owner') &&
$notepad->get('owner') != $GLOBALS['registry']->getAuth()) {
$label .= ' [' . $GLOBALS['registry']->convertUsername($notepad->get('owner'), false) . ']';
}
return $label;
}
/**
* Returns the real name, if available, of a user.
*
* @return string The real name
*/
public static function getUserName($uid)
{
static $names = array();
if (!isset($names[$uid])) {
$ident = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Identity')->create($uid);
$ident->setDefault($ident->getDefault());
$names[$uid] = $ident->getValue('fullname');
if (empty($names[$uid])) {
$names[$uid] = $uid;
}
}
return $names[$uid];
}
/**
* Comparison function for sorting notes by description.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer 1 if memo one is greater, -1 if memo two is greater; 0
* if they are equal.
*/
protected static function _sortByDesc($a, $b)
{
return strcoll($a['desc'], $b['desc']);
}
/**
* Comparison function for reverse sorting notes by description.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer -1 if note one is greater, 1 if note two is greater; 0
* if they are equal.
*/
protected static function _rsortByDesc($a, $b)
{
return self::_sortByDesc($b, $a);
}
/**
* Comparison function for sorting notes by notepad name.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer 1 if note one is greater, -1 if note two is greater;
* 0 if they are equal.
*/
protected static function _sortByNotepad($a, $b)
{
$aowner = $a['memolist_id'];
$bowner = $b['memolist_id'];
$ashare = $GLOBALS['mnemo_shares']->getShare($aowner);
$bshare = $GLOBALS['mnemo_shares']->getShare($bowner);
if ($aowner != $ashare->get('owner')) {
$aowner = $ashare->get('name');
}
if ($bowner != $bshare->get('owner')) {
$bowner = $bshare->get('name');
}
return strcoll($aowner, $bowner);
}
/**
* Comparison function for reverse sorting notes by notepad name.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer -1 if note one is greater, 1 if note two is greater;
* 0 if they are equal.
*/
protected static function _rsortByNotepad($a, $b)
{
return self::_sortByNotepad($b, $a);
}
/**
* Comparison function for sorting notes by modification date.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer 1 if note one is greater, -1 if note two is greater;
* 0 if they are equal.
*/
protected static function _sortByModDate($a, $b)
{
// Get notes` history
$history = $GLOBALS['injector']->getInstance('Horde_History');
$guidA = 'mnemo:' . $a['memolist_id'] . ':' . $a['uid'];
$guidB = 'mnemo:' . $b['memolist_id'] . ':' . $b['uid'];
// Gets the timestamp of the most recent modification to the note
$modDateA = $history->getActionTimestamp($guidA, 'modify');
$modDateB = $history->getActionTimestamp($guidB, 'modify');
// If the note hasn't been modified, get the creation timestamp
if ($modDateA == 0) {
$modDateA = $history->getActionTimestamp($guidA, 'add');
}
if ($modDateB == 0) {
$modDateB = $history->getActionTimestamp($guidB, 'add');
}
if ($modDateA == $modDateB) {
return 0;
}
return ($modDateA > $modDateB) ? 1 : -1;
}
/**
* Comparison function for reverse sorting notes by modification date.
*
* @param array $a Note one.
* @param array $b Note two.
*
* @return integer -1 if note one is greater, 1 if note two is greater,
* 0 if they are equal.
*/
protected static function _rsortByModDate($a, $b)
{
return self::_sortByModDate($b, $a);
}
/**
* Returns the specified permission for the current user.
*
* @param string $permission A permission, currently only 'max_notes'.
*
* @return mixed The value of the specified permission.
*/
public static function hasPermission($permission)
{
$perms = $GLOBALS['injector']->getInstance('Horde_Perms');
if (!$perms->exists('mnemo:' . $permission)) {
return true;
}
$allowed = $perms->getPermissions('mnemo:' . $permission, $GLOBALS['registry']->getAuth());
if (is_array($allowed)) {
switch ($permission) {
case 'max_notes':
$allowed = max($allowed);
break;
}
}
return $allowed;
}
/**
* Returns a note's passphrase for symmetric encryption from the session
* cache.
*
* @param string $id A note id.
*
* @return string The passphrase, if set.
*/
public static function getPassphrase($id)
{
return (strlen($id))
? $GLOBALS['session']->get('mnemo', 'passphrase/' . $id)
: null;
}
/**
* Stores a note's passphrase for symmetric encryption in the session
* cache.
*
* @param string $id A note id.
* @param string $passphrase The note's passphrase.
*
* @return boolean True
*/
public static function storePassphrase($id, $passphrase)
{
global $session;
$session->set('mnemo', 'passphrase/' . $id, $passphrase, $session::ENCRYPT);
}
/**
* Initial app setup code.
*
* Defines the following $GLOBALS (@TODO these should use the injector)
* mnemo_shares
* display_notepads
*/
public static function initialize()
{
$GLOBALS['mnemo_shares'] = $GLOBALS['injector']->getInstance('Horde_Core_Factory_Share')->create();
// Update the preference for which notepads to display. If the
// user doesn't have any selected notepads for view then fall
// back to some available notepad.
$GLOBALS['display_notepads'] = unserialize($GLOBALS['prefs']->getValue('display_notepads'));
if (($actionID = Horde_Util::getFormData('actionID')) !== null) {
$notepadId = Horde_Util::getFormData('display_notepad');
switch ($actionID) {
case 'add_displaylist':
if (!in_array($notepadId, $GLOBALS['display_notepads'])) {
$GLOBALS['display_notepads'][] = $notepadId;
}
break;
case 'remove_displaylist':
if (in_array($notepadId, $GLOBALS['display_notepads'])) {
$key = array_search($notepadId, $GLOBALS['display_notepads']);
unset($GLOBALS['display_notepads'][$key]);
}
}
}
// Make sure all notepads exist now, to save on checking later.
$_temp = ($GLOBALS['display_notepads']) ? $GLOBALS['display_notepads'] : array();
$_all = self::listNotepads();
$GLOBALS['display_notepads'] = array();
foreach ($_temp as $id) {
if (isset($_all[$id])) {
$GLOBALS['display_notepads'][] = $id;
}
}
// All notepads for guests.
if (!count($GLOBALS['display_notepads']) &&
!$GLOBALS['registry']->getAuth()) {
$GLOBALS['display_notepads'] = array_keys($_all);
}
/* If the user doesn't own a notepad, create one. */
$notepads = $GLOBALS['injector']->getInstance('Mnemo_Factory_Notepads')
->create();
if (($new_default = $notepads->ensureDefaultShare()) !== null) {
$GLOBALS['display_notepads'][] = $new_default;
$GLOBALS['prefs']->setValue('default_notepad', $new_default);
}
$GLOBALS['prefs']->setValue('display_notepads', serialize($GLOBALS['display_notepads']));
}
/**
* Returns the notepads that should be used for syncing.
*
* @param boolean $prune Remove notepads ids from the sync list that no
* longer exist. The values are pruned *after* the
* results are passed back to the client to give
* sync clients a chance to remove their entries.
*
* @return array An array of notepad ids.
*/
static public function getSyncNotepads($prune = false)
{
$haveRemoved = false;
$cs = unserialize($GLOBALS['prefs']->getValue('sync_notepads'));
if (!empty($cs)) {
if ($prune) {
$notepads = self::listNotepads(true, Horde_Perms::EDIT);
$cscopy = array_flip($cs);
foreach ($cs as $c) {
if (empty($notepads[$c])) {
unset($cscopy[$c]);
$haveRemoved = true;
}
}
if ($haveRemoved) {
$GLOBALS['prefs']->setValue('sync_notepads', serialize(array_flip($cscopy)));
}
}
return $cs;
}
if ($cs = self::getDefaultNotepad(Horde_Perms::EDIT)) {
return array($cs);
}
return array();
}
}
mnemo-4.2.9/lib/Tagger.php 0000664 0001750 0001750 00000003521 12654116457 013451 0 ustar jan jan
* @author Jan Schneider
* @license http://www.horde.org/licenses/asl ASL
* @package Mnemo
*/
class Mnemo_Tagger extends Horde_Core_Tagger
{
protected $_app = 'mnemo';
protected $_types = array('note');
/**
* Searches for resources that are tagged with all of the requested tags.
*
* @param array $tags Either a tag_id, tag_name or an array.
* @param array $filter Array of filter parameters.
* - user: (array) - only include objects owned by these users.
* - list (array) - restrict to notes contained in these notepads.
*
* @return array A hash of results.
*/
public function search($tags, $filter = array())
{
$args = array();
// These filters are mutually exclusive
if (array_key_exists('user', $filter)) {
// Items owned by specific user(s)
$args['userId'] = $filter['user'];
} elseif (!empty($filter['list'])) {
// Only events located in specific notepad(s)
if (!is_array($filter['list'])) {
$filter['list'] = array($filter['list']);
}
$args['listId'] = $filter['list'];
}
// Add the tags to the search
$args['tagId'] = $GLOBALS['injector']
->getInstance('Content_Tagger')
->ensureTags($tags);
$results = array();
$args['typeId'] = $this->_type_ids['note'];
return array_values($GLOBALS['injector']->getInstance('Content_Tagger')->getObjects($args));
}
} mnemo-4.2.9/locale/bg/LC_MESSAGES/mnemo.mo 0000664 0001750 0001750 00000212361 12654116457 016051 0 ustar jan jan t G \' x4 M y4 4 d 5 5 6 C <7 <