Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117756774
kolab_notes.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
25 KB
Referenced Files
None
Subscribers
None
kolab_notes.php
View Options
<?php
/**
* Kolab notes module
*
* Adds simple notes management features to the web client
*
* @author Thomas Bruederli <bruederli@kolabsys.com>
* @author Aleksander Machniak <machniak@apheleia-it.ch>
*
* Copyright (C) 2014-2025, Apheleia IT <contact@apheleia-it.ch>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class
kolab_notes
extends
rcube_plugin
{
public
$task
=
'?(?!login|logout).*'
;
public
$allowed_prefs
=
[
'kolab_notes_sort_col'
];
public
$rc
;
public
$driver
;
private
$ui
;
private
$message_notes
=
[];
private
$note
;
/**
* Required startup method of a Roundcube plugin
*/
public
function
init
()
{
$this
->
rc
=
rcube
::
get_instance
();
// proceed initialization in startup hook
$this
->
add_hook
(
'startup'
,
[
$this
,
'startup'
]);
}
/**
* Startup hook
*/
public
function
startup
(
$args
)
{
// the notes module can be enabled/disabled by the kolab_auth plugin
if
(
$this
->
rc
->
config
->
get
(
'kolab_notes_disabled'
,
false
)
||
!
$this
->
rc
->
config
->
get
(
'kolab_notes_enabled'
,
true
))
{
return
;
}
$this
->
register_task
(
'notes'
);
// load plugin configuration
$this
->
load_config
();
$driver
=
$this
->
rc
->
config
->
get
(
'kolab_notes_driver'
)
?:
'kolab'
;
$driver_class
=
"{$driver}_notes_driver"
;
require_once
__DIR__
.
"/drivers/{$driver}/{$driver_class}.php"
;
$this
->
driver
=
new
$driver_class
(
$this
);
// load localizations
$this
->
add_texts
(
'localization/'
,
$args
[
'task'
]
==
'notes'
&&
(!
$args
[
'action'
]
||
$args
[
'action'
]
==
'dialog-ui'
));
$this
->
rc
->
load_language
(
$_SESSION
[
'language'
],
[
'notes.notes'
=>
$this
->
gettext
(
'navtitle'
)]);
// add label for task title
if
(
$args
[
'task'
]
==
'notes'
)
{
$this
->
add_hook
(
'storage_init'
,
[
$this
,
'storage_init'
]);
// register task actions
$this
->
register_action
(
'index'
,
[
$this
,
'notes_view'
]);
$this
->
register_action
(
'fetch'
,
[
$this
,
'notes_fetch'
]);
$this
->
register_action
(
'get'
,
[
$this
,
'note_record'
]);
$this
->
register_action
(
'action'
,
[
$this
,
'note_action'
]);
$this
->
register_action
(
'list'
,
[
$this
,
'list_action'
]);
$this
->
register_action
(
'dialog-ui'
,
[
$this
,
'dialog_view'
]);
$this
->
register_action
(
'print'
,
[
$this
,
'print_note'
]);
if
(!
$this
->
rc
->
output
->
ajax_call
&&
in_array
(
$args
[
'action'
],
[
'dialog-ui'
,
'list'
]))
{
$this
->
load_ui
();
}
}
elseif
(
$args
[
'task'
]
==
'mail'
)
{
$this
->
add_hook
(
'storage_init'
,
[
$this
,
'storage_init'
]);
$this
->
add_hook
(
'message_compose'
,
[
$this
,
'mail_message_compose'
]);
if
(
in_array
(
$args
[
'action'
],
[
'show'
,
'preview'
,
'print'
]))
{
$this
->
add_hook
(
'message_load'
,
[
$this
,
'mail_message_load'
]);
$this
->
add_hook
(
'template_object_messagebody'
,
[
$this
,
'mail_messagebody_html'
]);
}
// add 'Append note' item to message menu
if
(
$this
->
api
->
output
->
type
==
'html'
&&
(
$_REQUEST
[
'_rel'
]
??
null
)
!=
'note'
)
{
$this
->
api
->
add_content
(
html
::
tag
(
'li'
,
[
'role'
=>
'menuitem'
],
$this
->
api
->
output
->
button
([
'command'
=>
'append-kolab-note'
,
'label'
=>
'kolab_notes.appendnote'
,
'type'
=>
'link'
,
'classact'
=>
'icon appendnote active'
,
'class'
=>
'icon appendnote disabled'
,
'innerclass'
=>
'icon note'
,
])
),
'messagemenu'
);
$this
->
api
->
output
->
add_label
(
'kolab_notes.appendnote'
,
'kolab_notes.editnote'
,
'kolab_notes.deletenotesconfirm'
,
'kolab_notes.entertitle'
,
'save'
,
'delete'
,
'cancel'
,
'close'
);
$this
->
include_script
(
'notes_mail.js'
);
}
}
if
(!
$this
->
rc
->
output
->
ajax_call
&&
empty
(
$this
->
rc
->
output
->
env
[
'framed'
]))
{
$this
->
load_ui
();
}
}
/**
* Hook into IMAP FETCH HEADER.FIELDS command and request MESSAGE-ID
*/
public
function
storage_init
(
$p
)
{
$p
[
'fetch_headers'
]
=
trim
(
$p
[
'fetch_headers'
]
.
' MESSAGE-ID'
);
return
$p
;
}
/**
* Load and initialize UI class
*/
private
function
load_ui
()
{
if
(!
$this
->
ui
)
{
require_once
(
$this
->
home
.
'/kolab_notes_ui.php'
);
$this
->
ui
=
new
kolab_notes_ui
(
$this
);
$this
->
ui
->
init
();
}
}
/******* UI functions ********/
/**
* Render main view of the tasklist task
*/
public
function
notes_view
()
{
$this
->
ui
->
init
();
$this
->
ui
->
init_templates
();
$this
->
rc
->
output
->
set_pagetitle
(
$this
->
gettext
(
'navtitle'
));
$this
->
rc
->
output
->
send
(
'kolab_notes.notes'
);
}
/**
* Deliver a rediced UI for inline (dialog)
*/
public
function
dialog_view
()
{
// resolve message reference
if
(
$msgref
=
rcube_utils
::
get_input_value
(
'_msg'
,
rcube_utils
::
INPUT_GPC
,
true
))
{
$storage
=
$this
->
rc
->
get_storage
();
[
$uid
,
$folder
]
=
explode
(
'-'
,
$msgref
,
2
);
if
(
$message
=
$storage
->
get_message_headers
(
$msgref
))
{
$message
->
folder
=
$folder
;
$this
->
rc
->
output
->
set_env
(
'kolab_notes_template'
,
[
'_from_mail'
=>
true
,
'title'
=>
$message
->
get
(
'subject'
),
'links'
=>
[
$this
->
driver
->
get_message_reference
(
$message
)],
]);
}
}
$this
->
ui
->
init_templates
();
$this
->
rc
->
output
->
send
(
'kolab_notes.dialogview'
);
}
/**
* Handler to retrieve note records for the given list and/or search query
*/
public
function
notes_fetch
()
{
$search
=
rcube_utils
::
get_input_value
(
'_q'
,
rcube_utils
::
INPUT_GPC
,
true
);
$list
=
rcube_utils
::
get_input_value
(
'_list'
,
rcube_utils
::
INPUT_GPC
);
$data
=
$this
->
driver
->
list_notes
(
$list
,
$search
);
$tags
=
[];
foreach
(
$data
as
$i
=>
$note
)
{
unset
(
$data
[
$i
][
'description'
]);
$tags
=
array_merge
(
$tags
,
$note
[
'tags'
]
??
[]);
$this
->
_client_encode
(
$data
[
$i
]);
}
$this
->
rc
->
output
->
command
(
'plugin.data_ready'
,
[
'list'
=>
$list
,
'search'
=>
$search
,
'data'
=>
$data
,
'tags'
=>
array_values
(
array_unique
(
$tags
)),
]);
}
/**
* Handler for delivering a full note record to the client
*/
public
function
note_record
()
{
$data
=
$this
->
driver
->
get_note
([
'uid'
=>
rcube_utils
::
get_input_value
(
'_id'
,
rcube_utils
::
INPUT_GPC
),
'list'
=>
rcube_utils
::
get_input_value
(
'_list'
,
rcube_utils
::
INPUT_GPC
),
]);
// encode for client use
if
(
is_array
(
$data
))
{
$this
->
_client_encode
(
$data
);
}
$this
->
rc
->
output
->
command
(
'plugin.render_note'
,
$data
);
}
/**
* Helper method to encode the given note record for use in the client
*/
private
function
_client_encode
(&
$note
)
{
foreach
(
$note
as
$key
=>
$prop
)
{
if
(
$key
[
0
]
==
'_'
||
$key
==
'x-custom'
)
{
unset
(
$note
[
$key
]);
}
}
foreach
([
'created'
,
'changed'
]
as
$key
)
{
if
(!
empty
(
$note
[
$key
])
&&
$note
[
$key
]
instanceof
DateTime
)
{
$note
[
$key
.
'_'
]
=
$note
[
$key
]->
format
(
'U'
);
$note
[
$key
]
=
$this
->
rc
->
format_date
(
$note
[
$key
]);
}
}
// clean HTML contents
if
(
$this
->
is_html
(
$note
))
{
$note
[
'html'
]
=
$this
->
wash_html
(
$note
[
'description'
]);
}
// convert link URIs references into structs
if
(
array_key_exists
(
'links'
,
$note
))
{
foreach
((
array
)
$note
[
'links'
]
as
$i
=>
$link
)
{
if
(
strpos
(
$link
,
'imap://'
)
===
0
&&
(
$msgref
=
$this
->
driver
->
get_message_reference
(
$link
)))
{
$note
[
'links'
][
$i
]
=
$msgref
;
}
}
}
return
$note
;
}
/**
* Handler for client-initiated actions on a single note record
*/
public
function
note_action
()
{
$action
=
rcube_utils
::
get_input_value
(
'_do'
,
rcube_utils
::
INPUT_POST
);
$note
=
rcube_utils
::
get_input_value
(
'_data'
,
rcube_utils
::
INPUT_POST
,
true
);
$success
=
$silent
=
$refresh
=
false
;
switch
(
$action
)
{
case
'new'
:
case
'edit'
:
$moved
=
true
;
if
(!
empty
(
$note
[
'_fromlist'
]))
{
$list_id
=
$note
[
'list'
];
$note
[
'list'
]
=
$note
[
'_fromlist'
];
unset
(
$note
[
'_fromlist'
]);
$moved
=
$this
->
driver
->
move_note
(
$note
,
$list_id
);
$note
[
'list'
]
=
$list_id
;
}
if
(
$moved
)
{
if
(
$success
=
$this
->
driver
->
save_note
(
$note
))
{
$refresh
=
$this
->
driver
->
get_note
(
$note
);
}
}
break
;
case
'move'
:
$uids
=
explode
(
','
,
$note
[
'uid'
]);
foreach
(
$uids
as
$uid
)
{
$note
[
'uid'
]
=
$uid
;
if
(!(
$success
=
$this
->
driver
->
move_note
(
$note
,
$note
[
'to'
])))
{
$refresh
=
$this
->
driver
->
get_note
(
$note
);
break
;
}
}
break
;
case
'delete'
:
$uids
=
explode
(
','
,
$note
[
'uid'
]);
foreach
(
$uids
as
$uid
)
{
$note
[
'uid'
]
=
$uid
;
if
(!(
$success
=
$this
->
driver
->
delete_note
(
$note
)))
{
$refresh
=
$this
->
driver
->
get_note
(
$note
);
break
;
}
}
break
;
case
'changelog'
:
$data
=
$this
->
driver
->
get_changelog
(
$note
);
if
(
is_array
(
$data
)
&&
!
empty
(
$data
))
{
$rcmail
=
$this
->
rc
;
$dtformat
=
$rcmail
->
config
->
get
(
'date_format'
)
.
' '
.
$this
->
rc
->
config
->
get
(
'time_format'
);
array_walk
(
$data
,
function
(&
$change
)
use
(
$rcmail
,
$dtformat
)
{
if
(
$change
[
'date'
])
{
$dt
=
rcube_utils
::
anytodatetime
(
$change
[
'date'
]);
if
(
$dt
instanceof
DateTime
)
{
$change
[
'date'
]
=
$rcmail
->
format_date
(
$dt
,
$dtformat
);
}
}
});
$this
->
rc
->
output
->
command
(
'plugin.note_render_changelog'
,
$data
);
}
else
{
$this
->
rc
->
output
->
command
(
'plugin.note_render_changelog'
,
false
);
}
$silent
=
true
;
break
;
case
'diff'
:
$silent
=
true
;
$data
=
$this
->
driver
->
get_diff
(
$note
,
$note
[
'rev1'
],
$note
[
'rev2'
]);
if
(
is_array
(
$data
))
{
$this
->
rc
->
output
->
command
(
'plugin.note_show_diff'
,
$data
);
}
else
{
$this
->
rc
->
output
->
command
(
'display_message'
,
$this
->
gettext
(
'objectdiffnotavailable'
),
'error'
);
}
break
;
case
'show'
:
if
(
$rec
=
$this
->
driver
->
get_revison
(
$note
,
$note
[
'rev'
]))
{
$this
->
rc
->
output
->
command
(
'plugin.note_show_revision'
,
$this
->
_client_encode
(
$rec
));
}
else
{
$this
->
rc
->
output
->
command
(
'display_message'
,
$this
->
gettext
(
'objectnotfound'
),
'error'
);
}
$silent
=
true
;
break
;
case
'restore'
:
if
(
$this
->
driver
->
restore_revision
(
$note
,
$note
[
'rev'
]))
{
$refresh
=
$this
->
driver
->
get_note
(
$note
);
$this
->
rc
->
output
->
command
(
'display_message'
,
$this
->
gettext
([
'name'
=>
'objectrestoresuccess'
,
'vars'
=>
[
'rev'
=>
$note
[
'rev'
]]]),
'confirmation'
);
$this
->
rc
->
output
->
command
(
'plugin.close_history_dialog'
);
}
else
{
$this
->
rc
->
output
->
command
(
'display_message'
,
$this
->
gettext
(
'objectrestoreerror'
),
'error'
);
}
$silent
=
true
;
break
;
}
// show confirmation/error message
if
(
$success
)
{
$this
->
rc
->
output
->
show_message
(
'successfullysaved'
,
'confirmation'
);
}
elseif
(!
$silent
)
{
$last_error
=
$this
->
driver
->
last_error
();
$error_msg
=
$this
->
gettext
(
'errorsaving'
)
.
(!
empty
(
$last_error
)
?
': '
.
$last_error
:
''
);
$this
->
rc
->
output
->
show_message
(
$error_msg
,
'error'
);
}
// unlock client
$this
->
rc
->
output
->
command
(
'plugin.unlock_saving'
);
if
(
$refresh
)
{
$this
->
rc
->
output
->
command
(
'plugin.update_note'
,
$this
->
_client_encode
(
$refresh
));
}
}
/**
* Render the template for printing with placeholders
*/
public
function
print_note
()
{
$uid
=
rcube_utils
::
get_input_value
(
'_uid'
,
rcube_utils
::
INPUT_GET
);
$list
=
rcube_utils
::
get_input_value
(
'_list'
,
rcube_utils
::
INPUT_GET
);
$this
->
note
=
$this
->
driver
->
get_note
([
'uid'
=>
$uid
,
'list'
=>
$list
]);
// encode for client use
if
(
is_array
(
$this
->
note
))
{
$this
->
_client_encode
(
$this
->
note
);
}
$this
->
rc
->
output
->
set_pagetitle
(
$this
->
note
[
'title'
]);
$this
->
rc
->
output
->
add_handlers
([
'noteheader'
=>
[
$this
,
'print_note_header'
],
'notebody'
=>
[
$this
,
'print_note_body'
],
]);
$this
->
include_script
(
'notes.js'
);
$this
->
rc
->
output
->
send
(
'kolab_notes.print'
);
}
public
function
print_note_header
()
{
$tags
=
array_map
([
'rcube'
,
'Q'
],
(
array
)
$this
->
note
[
'tags'
]);
$tags
=
implode
(
' '
,
$tags
);
return
html
::
tag
(
'h1'
,
[
'id'
=>
'notetitle'
],
rcube
::
Q
(
$this
->
note
[
'title'
]))
.
html
::
div
([
'id'
=>
'notetags'
,
'class'
=>
'tagline'
],
$tags
)
.
html
::
div
(
'dates'
,
html
::
label
(
null
,
rcube
::
Q
(
$this
->
gettext
(
'created'
)))
.
html
::
span
([
'id'
=>
'notecreated'
],
rcube
::
Q
(
$this
->
note
[
'created'
]))
.
html
::
label
(
null
,
rcube
::
Q
(
$this
->
gettext
(
'changed'
)))
.
html
::
span
([
'id'
=>
'notechanged'
],
rcube
::
Q
(
$this
->
note
[
'changed'
]))
);
}
public
function
print_note_body
()
{
return
$this
->
note
[
'html'
]
??
rcube
::
Q
(
$this
->
note
[
'description'
]);
}
/**
* Handler for client requests to list (aka folder) actions
*/
public
function
list_action
()
{
$action
=
rcube_utils
::
get_input_value
(
'_do'
,
rcube_utils
::
INPUT_GPC
);
$list
=
rcube_utils
::
get_input_value
(
'_list'
,
rcube_utils
::
INPUT_GPC
,
true
);
$success
=
$update_cmd
=
false
;
$jsenv
=
[];
if
(
empty
(
$action
))
{
$action
=
rcube_utils
::
get_input_value
(
'action'
,
rcube_utils
::
INPUT_GPC
);
}
switch
(
$action
)
{
case
'form-new'
:
case
'form-edit'
:
$this
->
ui
->
list_editform
(
$action
,
$list
[
'id'
]);
exit
;
case
'new'
:
$list
[
'subscribed'
]
=
true
;
if
(
$success
=
$this
->
driver
->
list_create
(
$list
))
{
$update_cmd
=
'plugin.update_list'
;
$list
[
'_reload'
]
=
true
;
}
break
;
case
'edit'
:
$oldid
=
$list
[
'id'
];
$oldparent
=
$this
->
driver
->
list_get
(
$list
[
'id'
])[
'parent'
]
??
null
;
if
(
$success
=
$this
->
driver
->
list_update
(
$list
))
{
$update_cmd
=
'plugin.update_list'
;
$list
[
'_reload'
]
=
$list
[
'parent'
]
!=
$oldparent
;
if
(
$oldid
!=
$list
[
'id'
])
{
$list
[
'newid'
]
=
$list
[
'id'
];
$list
[
'id'
]
=
$oldid
;
}
}
break
;
case
'delete'
:
if
(
$success
=
$this
->
driver
->
list_delete
(
$list
))
{
$update_cmd
=
'plugin.destroy_list'
;
}
break
;
case
'search'
:
$this
->
load_ui
();
$q
=
rcube_utils
::
get_input_value
(
'q'
,
rcube_utils
::
INPUT_GPC
);
$source
=
rcube_utils
::
get_input_value
(
'source'
,
rcube_utils
::
INPUT_GPC
);
$results
=
[];
foreach
((
array
)
$this
->
driver
->
search_lists
(
$q
,
$source
)
as
$id
=>
$prop
)
{
$editname
=
$prop
[
'editname'
];
unset
(
$prop
[
'editname'
]);
// force full name to be displayed
// let the UI generate HTML and CSS representation for this folder
$html
=
$this
->
ui
->
folder_list_item
(
$id
,
$prop
,
$jsenv
,
true
);
$prop
+=
$jsenv
[
$id
]
??
[];
// @phpstan-ignore-line
$prop
[
'editname'
]
=
$editname
;
$prop
[
'html'
]
=
$html
;
$results
[]
=
$prop
;
}
if
(
$this
->
driver
->
has_more
)
{
$this
->
rc
->
output
->
show_message
(
'autocompletemore'
,
'notice'
);
}
$this
->
rc
->
output
->
command
(
'multi_thread_http_response'
,
$results
,
rcube_utils
::
get_input_value
(
'_reqid'
,
rcube_utils
::
INPUT_GPC
));
return
;
case
'subscribe'
:
$success
=
$this
->
driver
->
list_subscribe
(
$list
);
break
;
}
$this
->
rc
->
output
->
command
(
'plugin.unlock_saving'
);
if
(
$success
)
{
$this
->
rc
->
output
->
show_message
(
'successfullysaved'
,
'confirmation'
);
if
(
$update_cmd
)
{
$this
->
rc
->
output
->
command
(
$update_cmd
,
$list
);
}
}
else
{
$last_error
=
$this
->
driver
->
last_error
();
$error_msg
=
$this
->
gettext
(
'errorsaving'
)
.
(!
empty
(
$last_error
)
?
': '
.
$last_error
:
''
);
$this
->
rc
->
output
->
show_message
(
$error_msg
,
'error'
);
}
}
/**
* Hook to add note attachments to message compose if the according parameter is present.
* This completes the 'send note by mail' feature.
*/
public
function
mail_message_compose
(
$args
)
{
if
(!
empty
(
$args
[
'param'
][
'with_notes'
]))
{
$uids
=
explode
(
','
,
$args
[
'param'
][
'with_notes'
]);
$list
=
$args
[
'param'
][
'notes_list'
];
foreach
(
$uids
as
$uid
)
{
if
(
$note
=
$this
->
driver
->
get_note
([
'uid'
=>
$uid
,
'list'
=>
$list
]))
{
$data
=
$this
->
note2message
(
$note
);
$args
[
'attachments'
][]
=
[
'name'
=>
abbreviate_string
(
$note
[
'title'
],
50
,
''
),
'mimetype'
=>
'message/rfc822'
,
'data'
=>
$data
,
'size'
=>
strlen
(
$data
),
];
if
(
empty
(
$args
[
'param'
][
'subject'
]))
{
$args
[
'param'
][
'subject'
]
=
$note
[
'title'
];
}
}
}
unset
(
$args
[
'param'
][
'with_notes'
],
$args
[
'param'
][
'notes_list'
]);
}
return
$args
;
}
/**
* Lookup backend storage and find notes associated with the given message
*/
public
function
mail_message_load
(
$p
)
{
if
(
empty
(
$p
[
'object'
]->
headers
->
others
[
'x-kolab-type'
]))
{
$p
[
'object'
]->
headers
->
folder
=
$p
[
'object'
]->
folder
;
$this
->
message_notes
=
$this
->
driver
->
get_message_notes
(
$p
[
'object'
]->
headers
);
}
}
/**
* Handler for 'messagebody_html' hook
*/
public
function
mail_messagebody_html
(
$args
)
{
$html
=
''
;
foreach
(
$this
->
message_notes
as
$note
)
{
$html
.=
html
::
a
([
'href'
=>
$this
->
rc
->
url
([
'task'
=>
'notes'
,
'_list'
=>
$note
[
'list'
],
'_id'
=>
$note
[
'uid'
]]),
'class'
=>
'kolabnotesref'
,
'rel'
=>
$note
[
'uid'
]
.
'@'
.
$note
[
'list'
],
'target'
=>
'_blank'
,
],
rcube
::
Q
(
$note
[
'title'
]));
}
// prepend note links to message body
if
(
$html
)
{
$this
->
load_ui
();
$args
[
'content'
]
=
html
::
div
(
'kolabmessagenotes boxinformation'
,
$html
)
.
$args
[
'content'
];
}
return
$args
;
}
/**
* Determine whether the given note is HTML formatted
*/
public
static
function
is_html
(
$note
)
{
// check for opening and closing <html> or <body> tags
return
!
empty
(
$note
[
'description'
])
&&
preg_match
(
'/<(html|body)(
\s
+[a-z]|>)/'
,
$note
[
'description'
],
$m
)
&&
strpos
(
$note
[
'description'
],
'</'
.
$m
[
1
]
.
'>'
)
>
0
;
}
/**
* Build an RFC 822 message from the given note
*/
private
function
note2message
(
$note
)
{
$message
=
new
Mail_mime
(
"
\r\n
"
);
$message
->
setParam
(
'text_encoding'
,
'8bit'
);
$message
->
setParam
(
'html_encoding'
,
'quoted-printable'
);
$message
->
setParam
(
'head_encoding'
,
'quoted-printable'
);
$message
->
setParam
(
'head_charset'
,
RCUBE_CHARSET
);
$message
->
setParam
(
'html_charset'
,
RCUBE_CHARSET
);
$message
->
setParam
(
'text_charset'
,
RCUBE_CHARSET
);
$message
->
headers
([
'Subject'
=>
$note
[
'title'
],
'Date'
=>
$note
[
'changed'
]->
format
(
'r'
),
]);
if
(
$this
->
is_html
(
$note
))
{
$message
->
setHTMLBody
(
$note
[
'description'
]);
// add a plain text version of the note content as an alternative part.
$h2t
=
new
rcube_html2text
(
$note
[
'description'
],
false
,
true
,
0
,
RCUBE_CHARSET
);
$plain_part
=
rcube_mime
::
wordwrap
(
$h2t
->
get_text
(),
$this
->
rc
->
config
->
get
(
'line_length'
,
72
),
"
\r\n
"
,
false
,
RCUBE_CHARSET
);
$plain_part
=
trim
(
wordwrap
(
$plain_part
,
998
,
"
\r\n
"
,
true
));
// make sure all line endings are CRLF
$plain_part
=
preg_replace
(
'/
\r
?
\n
/'
,
"
\r\n
"
,
$plain_part
);
$message
->
setTXTBody
(
$plain_part
);
}
else
{
$message
->
setTXTBody
(
$note
[
'description'
]);
}
return
$message
->
getMessage
();
}
/**
* Sanity checks/cleanups HTML content
*/
public
function
wash_html
(
$html
)
{
// Add header with charset spec., washtml cannot work without that
$html
=
'<html><head>'
.
'<meta http-equiv="Content-Type" content="text/html; charset='
.
RCUBE_CHARSET
.
'" />'
.
'</head><body>'
.
$html
.
'</body></html>'
;
// clean HTML with washtml by Frederic Motte
$wash_opts
=
[
'show_washed'
=>
false
,
'allow_remote'
=>
1
,
'charset'
=>
RCUBE_CHARSET
,
'html_elements'
=>
[
'html'
,
'head'
,
'meta'
,
'body'
,
'link'
],
'html_attribs'
=>
[
'rel'
,
'type'
,
'name'
,
'http-equiv'
],
];
// initialize HTML washer
$washer
=
new
rcube_washtml
(
$wash_opts
);
$washer
->
add_callback
(
'form'
,
[
$this
,
'_washtml_callback'
]);
$washer
->
add_callback
(
'a'
,
[
$this
,
'_washtml_callback'
]);
// Remove non-UTF8 characters
$html
=
rcube_charset
::
clean
(
$html
);
$html
=
$washer
->
wash
(
$html
);
// remove unwanted comments (produced by washtml)
$html
=
preg_replace
(
'/<!--[^>]+-->/'
,
''
,
$html
);
return
$html
;
}
/**
* Callback function for washtml cleaning class
*/
public
function
_washtml_callback
(
$tagname
,
$attrib
,
$content
,
$washtml
)
{
switch
(
$tagname
)
{
case
'form'
:
$out
=
html
::
div
(
'form'
,
$content
);
break
;
case
'a'
:
// strip temporary link tags from plain-text markup
$attrib
=
html
::
parse_attrib_string
(
$attrib
);
if
(!
empty
(
$attrib
[
'class'
])
&&
strpos
(
$attrib
[
'class'
],
'x-templink'
)
!==
false
)
{
// remove link entirely
if
(
strpos
(
$attrib
[
'href'
],
html_entity_decode
(
$content
))
!==
false
)
{
$out
=
$content
;
break
;
}
$attrib
[
'class'
]
=
trim
(
str_replace
(
'x-templink'
,
''
,
$attrib
[
'class'
]));
}
$out
=
html
::
a
(
$attrib
,
$content
);
break
;
default
:
$out
=
''
;
}
return
$out
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Apr 4, 8:51 AM (2 w, 5 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
23/dd/09edc1b714bd00fdd7df07273ce8
Default Alt Text
kolab_notes.php (25 KB)
Attached To
Mode
rRPK roundcubemail-plugins-kolab
Attached
Detach File
Event Timeline