Fix title escaping in html and rST mode
[grauphel.git] / controller / notescontroller.php
1 <?php
2 /**
3  * Part of grauphel
4  *
5  * PHP version 5
6  *
7  * @category  Tools
8  * @package   Grauphel
9  * @author    Christian Weiske <cweiske@cweiske.de>
10  * @copyright 2014 Christian Weiske
11  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
12  * @link      http://cweiske.de/grauphel.htm
13  */
14 namespace OCA\Grauphel\Controller;
15
16 use \OCP\AppFramework\Controller;
17 use \OCP\AppFramework\Http\TemplateResponse;
18 use \OCA\Grauphel\Lib\Client;
19 use \OCA\Grauphel\Lib\TokenStorage;
20 use \OCA\Grauphel\Lib\Response\ErrorResponse;
21
22 /**
23  * Owncloud frontend: Notes
24  *
25  * @category  Tools
26  * @package   Grauphel
27  * @author    Christian Weiske <cweiske@cweiske.de>
28  * @copyright 2014 Christian Weiske
29  * @license   http://www.gnu.org/licenses/agpl.html GNU AGPL v3
30  * @version   Release: @package_version@
31  * @link      http://cweiske.de/grauphel.htm
32  */
33 class NotesController extends Controller
34 {
35     /**
36      * constructor of the controller
37      *
38      * @param string   $appName Name of the app
39      * @param IRequest $request Instance of the request
40      */
41     public function __construct($appName, \OCP\IRequest $request, $user)
42     {
43         parent::__construct($appName, $request);
44         $this->user   = $user;
45
46         //default http header: we assume something is broken
47         header('HTTP/1.0 500 Internal Server Error');
48     }
49
50     /**
51      * Output a note as a standalone HTML file
52      *
53      * @NoAdminRequired
54      * @NoCSRFRequired
55      */
56     public function html($guid)
57     {
58         $note = $this->getNotes()->load($guid, false);
59         if ($note === null) {
60             $res = new ErrorResponse('Note does not exist');
61             $res->setStatus(\OCP\AppFramework\Http::STATUS_NOT_FOUND);
62             return $res;
63         }
64
65         $xw = new \XMLWriter();
66         $xw->openMemory();
67         $xw->setIndent(true);
68         $xw->setIndentString(' ');
69         $xw->startDocument('1.0', 'utf-8');
70         $xw->writeRaw(
71             '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
72             . ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
73             . "\n"
74         );
75
76         $xw->startElementNS(null, 'html', 'http://www.w3.org/1999/xhtml');
77
78         //head
79         $xw->startElement('head');
80         $xw->writeElement(
81             'title',
82             htmlspecialchars_decode($note->title, ENT_QUOTES | ENT_HTML5)
83         );
84
85         $xw->startElement('meta');
86         $xw->writeAttribute('name', 'author');
87         $xw->writeAttribute('content', $this->user->getDisplayName());
88         $xw->endElement();
89
90         $xw->startElement('meta');
91         $xw->writeAttribute('http-equiv', 'Content-Type');
92         $xw->writeAttribute('content', 'text/html; charset=utf-8');
93         $xw->endElement();
94
95         $xw->startElement('link');
96         $xw->writeAttribute('rel', 'schema.DC');
97         $xw->writeAttribute('href', 'http://purl.org/dc/elements/1.1/');
98         $xw->endElement();
99
100         $xw->startElement('meta');
101         $xw->writeAttribute('name', 'DC.date.created');
102         $xw->writeAttribute(
103             'content', date('c', strtotime($note->{'create-date'}))
104         );
105         $xw->endElement();
106
107         $xw->startElement('meta');
108         $xw->writeAttribute('name', 'DC.date.modified');
109         $xw->writeAttribute(
110             'content', date('c', strtotime($note->{'last-change-date'}))
111         );
112         $xw->endElement();
113
114         $xw->endElement();//head
115
116         //body
117         $xw->startElement('body');
118         $xw->writeElement(
119             'h1', htmlspecialchars_decode($note->title, ENT_QUOTES | ENT_HTML5)
120         );
121
122         $converter = new \OCA\Grauphel\Converter\CleanHtml();
123         $converter->internalLinkHandler = array($this, 'htmlNoteLinkHandler');
124         try {
125             $xw->writeRaw(
126                 $converter->convert($note->{'note-content'})
127             );
128         } catch (\OCA\Grauphel\Converter\Exception $e) {
129             $res = new ErrorResponse(
130                 'Error converting note to HTML.'
131                 . ' Please report a bug to the grauphel developers.'
132             );
133             $res->setStatus(\OCP\AppFramework\Http::STATUS_NOT_FOUND);
134             return $res;
135         }
136
137         $xw->endElement();//body
138
139         $xw->endElement();//html
140         return new \OCA\Grauphel\Response\XmlResponse($xw->outputMemory());
141     }
142
143     public function htmlNoteLinkHandler($noteTitle)
144     {
145         return urlencode($noteTitle) . '.html';
146     }
147
148     /**
149      * Output a note as a standalone text file
150      *
151      * @NoAdminRequired
152      * @NoCSRFRequired
153      */
154     public function text($guid)
155     {
156         $note = $this->getNotes()->load($guid, false);
157         if ($note === null) {
158             $res = new ErrorResponse('Note does not exist');
159             $res->setStatus(\OCP\AppFramework\Http::STATUS_NOT_FOUND);
160             return $res;
161         }
162
163         $converter = new \OCA\Grauphel\Converter\ReStructuredText();
164         $converter->internalLinkHandler = array($this, 'textNoteLinkHandler');
165         try {
166             $title = htmlspecialchars_decode($note->title, ENT_QUOTES | ENT_HTML5);
167             $text = $title . "\n"
168                 . str_repeat('*', strlen($title)) . "\n"
169                 . "\n";
170             $text .= $converter->convert($note->{'note-content'});
171             return new \OCA\Grauphel\Response\TextResponse($text);
172         } catch (\OCA\Grauphel\Converter\Exception $e) {
173             $res = new ErrorResponse(
174                 'Error converting note to reStructuredText.'
175                 . ' Please report a bug to the grauphel developers.'
176             );
177             $res->setStatus(\OCP\AppFramework\Http::STATUS_NOT_FOUND);
178             return $res;
179         }
180     }
181
182     public function textNoteLinkHandler($noteTitle)
183     {
184         return $noteTitle;
185     }
186
187     /**
188      * Output a note in tomboy XML format
189      *
190      * @link https://wiki.gnome.org/Apps/Tomboy/NoteXmlFormat
191      *
192      * @NoAdminRequired
193      * @NoCSRFRequired
194      */
195     public function xml($guid)
196     {
197         $note = $this->getNotes()->load($guid, false);
198         if ($note === null) {
199             $res = new ErrorResponse('Note does not exist');
200             $res->setStatus(\OCP\AppFramework\Http::STATUS_NOT_FOUND);
201             return $res;
202         }
203
204         $xw = new \XMLWriter();
205         $xw->openMemory();
206         $xw->startDocument('1.0', 'utf-8');
207
208         $xw->startElementNS(null, 'note', 'http://beatniksoftware.com/tomboy');
209         $xw->writeAttribute('version', '0.3');
210         $xw->writeAttribute('xmlns:link', 'http://beatniksoftware.com/tomboy/link');
211         $xw->writeAttribute('xmlns:size', 'http://beatniksoftware.com/tomboy/size');
212
213         $xw->writeElement('title', $note->title);
214         $xw->startElement('text');
215         $xw->writeAttribute('xml:space', 'preserve');
216
217         $xw->startElement('note-content');
218         $xw->writeAttribute('version', $note->{'note-content-version'});
219         $xw->writeRaw($note->{'note-content'});
220         $xw->endElement();//note-content
221         $xw->endElement();//text
222
223         $xw->writeElement('last-change-date', $note->{'last-change-date'});
224         $xw->writeElement('last-metadata-change-date', $note->{'last-metadata-change-date'});
225         $xw->writeElement('create-date', $note->{'create-date'});
226         $xw->writeElement('cursor-position', 0);
227         $xw->writeElement('width', 450);
228         $xw->writeElement('height', 360);
229         $xw->writeElement('x', 0);
230         $xw->writeElement('y', 0);
231         $xw->writeElement('open-on-startup', $note->{'open-on-startup'});
232
233         $xw->endElement();//note
234
235         return new \OCA\Grauphel\Response\XmlResponse($xw->outputMemory());
236     }
237
238     protected function getNotes()
239     {
240         $username = $this->user->getUid();
241         $notes  = new \OCA\Grauphel\Lib\NoteStorage($this->urlGen);
242         $notes->setUsername($username);
243         return $notes;
244     }
245 }
246 ?>