mirror of
https://github.com/maxpozdeev/mytinytodo.git
synced 2026-03-11 08:55:27 +00:00
* do not allow urls and any html elements in task title (escape all); format the note in php (not js) using mttMarkup_v1
This commit is contained in:
parent
8760404245
commit
f035fa3464
5 changed files with 39 additions and 22 deletions
|
|
@ -231,7 +231,7 @@ elseif(isset($_GET['editNote']))
|
|||
$db->dq("UPDATE {$db->prefix}todolist SET note=?,d_edited=? WHERE id=$id", array($note, time()) );
|
||||
$t = array();
|
||||
$t['total'] = 1;
|
||||
$t['list'][] = array('id'=>$id, 'note'=>nl2br(escapeTags($note)), 'noteText'=>(string)$note);
|
||||
$t['list'][] = array('id'=>$id, 'note'=>mttMarkup_v1($note), 'noteText'=>(string)$note);
|
||||
jsonExit($t);
|
||||
}
|
||||
elseif(isset($_GET['editTask']))
|
||||
|
|
@ -544,7 +544,7 @@ function prepareTaskRow($r)
|
|||
|
||||
return array(
|
||||
'id' => $r['id'],
|
||||
'title' => escapeTags($r['title']),
|
||||
'title' => htmlspecialchars( $r['title'] ),
|
||||
'listId' => $r['list_id'],
|
||||
'date' => htmlarray($dCreated),
|
||||
'dateInt' => (int)$r['d_created'],
|
||||
|
|
@ -556,7 +556,7 @@ function prepareTaskRow($r)
|
|||
'dateCompletedInlineTitle' => htmlarray(sprintf($lang->get('taskdate_inline_completed'), $dCompleted)),
|
||||
'compl' => (int)$r['compl'],
|
||||
'prio' => $r['prio'],
|
||||
'note' => nl2br(escapeTags($r['note'])),
|
||||
'note' => mttMarkup_v1($r['note']),
|
||||
'noteText' => (string)$r['note'],
|
||||
'ow' => (int)$r['ow'],
|
||||
'tags' => htmlarray($r['tags']),
|
||||
|
|
|
|||
|
|
@ -226,8 +226,8 @@ li.task-completed .task-note-block .task-note { text-decoration:line-through; }
|
|||
.invisible { visibility:hidden; }
|
||||
.in500 { width:500px; color:#444444; }
|
||||
.in100 { width:100px; color:#444444; }
|
||||
.task-note span a { color:#777777; }
|
||||
.task-note span a:hover { color:#af0000; }
|
||||
.task-note a { color:#777777; }
|
||||
.task-note a:hover { color:#af0000; }
|
||||
|
||||
.task-prio { padding-left:2px; padding-right:2px; margin-left:0px; margin-right:5px; cursor:default; }
|
||||
.prio-neg { background-color:#3377ff; color:#ffffff; }
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ while($r = $q->fetch_assoc($q))
|
|||
}
|
||||
if($r['tags'] != '') $a[] = $lang->get('tags'). ": ". str_replace(',', ', ', $r['tags']);
|
||||
if($r['compl']) $a[] = $lang->get('taskdate_completed'). ": ". timestampToDatetime($r['d_completed']);
|
||||
$r['title'] = strip_tags($r['title']);
|
||||
$r['note'] = escapeTags($r['note']);
|
||||
$r['_descr'] = nl2br($r['note']). ($a && $r['note']!='' ? "<br/><br/>" : ""). implode("<br/>", htmlarray($a));
|
||||
$r['title'] = htmlspecialchars( $r['title'] );
|
||||
$r['note'] = mttMarkup_v1($r['note']);
|
||||
$r['_descr'] = $r['note']. ($a && $r['note']!='' ? "<br/><br/>" : ""). implode("<br/>", htmlarray($a));
|
||||
$data[] = $r;
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ function printRss($listData, $data)
|
|||
$d = gmdate('r', $v[$listData['_uid_field']]);
|
||||
$guid = $listData['id'].'-'.$v['id'].'-'.$v[$listData['_uid_field']];
|
||||
|
||||
$s .= "<item>\n<title><![CDATA[". str_replace("]]>", "]]]]><![CDATA[>", $v['title']). "]]></title>\n".
|
||||
$s .= "<item>\n<title>${v['title']}</title>\n".
|
||||
"<link>$link</link>\n".
|
||||
"<pubDate>$d</pubDate>\n".
|
||||
"<description><![CDATA[". $v['_descr']. "]]></description>\n".
|
||||
|
|
|
|||
|
|
@ -212,15 +212,26 @@ function url_dir($url, $onlyPath = 1)
|
|||
return '/';
|
||||
}
|
||||
|
||||
function escapeTags($s)
|
||||
// Convert note's raw text to html with allowed elements (b,i,u,s and raw urls)
|
||||
function mttMarkup_v1($s)
|
||||
{
|
||||
//hide allowed elements from escaping
|
||||
$c1 = chr(1);
|
||||
$c2 = chr(2);
|
||||
$s = preg_replace("~<b>([\s\S]*?)</b>~i", "${c1}b${c2}\$1${c1}/b${c2}", $s);
|
||||
$s = preg_replace("~<i>([\s\S]*?)</i>~i", "${c1}i${c2}\$1${c1}/i${c2}", $s);
|
||||
$s = preg_replace("~<u>([\s\S]*?)</u>~i", "${c1}u${c2}\$1${c1}/u${c2}", $s);
|
||||
$s = preg_replace("~<s>([\s\S]*?)</s>~i", "${c1}s${c2}\$1${c1}/s${c2}", $s);
|
||||
$s = str_replace(array($c1, $c2), array('<','>'), htmlspecialchars($s));
|
||||
$s = htmlspecialchars($s); //escape all elements, except above
|
||||
$s = str_replace( [$c1, $c2], ['<','>'], $s ); //unhide
|
||||
$s = nl2br($s);
|
||||
|
||||
// make links from text starting with 'www.'
|
||||
$s = preg_replace( "/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/i" , '$1<a href="http://$2" target="_blank">$2</a>$4' , $s );
|
||||
|
||||
// make link from text starting with protocol like 'http://'
|
||||
$s = preg_replace( "/(^|\s|>)([a-z]+:\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/i" , '$1<a href="$2" target="_blank">$2</a>$4' , $s);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -956,7 +956,7 @@ function loadTasks(opts)
|
|||
function prepareTaskStr(item, noteExp)
|
||||
{
|
||||
return '<li id="taskrow_'+item.id+'" class="task-row ' + (item.compl?'task-completed ':'') + item.dueClass + (item.note!=''?' task-has-note':'') +
|
||||
((curList.showNotes && item.note != '') || noteExp ? ' task-expanded' : '') + prepareTagsClass(item.tags_ids) + '"><div class="task-container">' +
|
||||
((curList.showNotes && item.note != '') || noteExp ? ' task-expanded' : '') + prepareDomClassOfTags(item.tags_ids) + '"><div class="task-container">' +
|
||||
prepareTaskBlocks(item) + "</div></li>\n";
|
||||
};
|
||||
_mtt.prepareTaskStr = prepareTaskStr;
|
||||
|
|
@ -975,7 +975,7 @@ function prepareTaskBlocks(item)
|
|||
'<div class="task-middle-top">' +
|
||||
'<div class="task-through">' +
|
||||
preparePrio(item.prio,id) +
|
||||
'<span class="task-title">' + prepareHtml(item.title) + '</span> ' +
|
||||
'<span class="task-title">' + prepareTaskTitleInlineHtml(item.title) + '</span> ' +
|
||||
(curList.id == -1 ? '<span class="task-listname">'+ tabLists.get(item.listId).name +'</span>' : '') +
|
||||
prepareTagsStr(item) +
|
||||
'<span class="task-date">'+item.dateInlineTitle+'</span>' +
|
||||
|
|
@ -984,7 +984,7 @@ function prepareTaskBlocks(item)
|
|||
'</div>' +
|
||||
|
||||
'<div class="task-note-block">' +
|
||||
'<div id="tasknote'+id+'" class="task-note"><span>'+prepareHtml(item.note)+'</span></div>' +
|
||||
'<div id="tasknote' + id + '" class="task-note">' + prepareTaskNoteInlineHtml(item.note) + '</div>' +
|
||||
'<div id="tasknotearea'+id+'" class="task-note-area"><textarea id="notetext'+id+'"></textarea>'+
|
||||
'<span class="task-note-actions"><a href="#" class="mtt-action-note-save">'+_mtt.lang.get('actionNoteSave') +
|
||||
'</a> | <a href="#" class="mtt-action-note-cancel">'+_mtt.lang.get('actionNoteCancel')+'</a></span>' +
|
||||
|
|
@ -996,13 +996,19 @@ function prepareTaskBlocks(item)
|
|||
};
|
||||
_mtt.prepareTaskBlocks = prepareTaskBlocks;
|
||||
|
||||
function prepareHtml(s)
|
||||
function prepareTaskTitleInlineHtml(s)
|
||||
{
|
||||
// make URLs clickable
|
||||
s = s.replace(/(^|\s|>)(www\.([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/gi, '$1<a href="http://$2" target="_blank">$2</a>$4');
|
||||
return s.replace(/(^|\s|>)((?:http|https|ftp):\/\/([\w\#$%&~\/.\-\+;:=,\?\[\]@]+?))(,|\.|:|)?(?=\s|"|<|>|\"|<|>|$)/ig, '$1<a href="$2" target="_blank">$2</a>$4');
|
||||
// Task title is already escaped on php back-end
|
||||
return s;
|
||||
}
|
||||
_mtt.prepareTaskTitleInlineHtml = prepareTaskTitleInlineHtml;
|
||||
|
||||
function prepareTaskNoteInlineHtml(s)
|
||||
{
|
||||
// Task note is already escaped on php back-end
|
||||
return s;
|
||||
};
|
||||
_mtt.prepareHtml = prepareHtml;
|
||||
_mtt.prepareTaskNoteInlineHtml = prepareTaskNoteInlineHtml;
|
||||
|
||||
function preparePrio(prio,id)
|
||||
{
|
||||
|
|
@ -1027,7 +1033,7 @@ function prepareTagsStr(item)
|
|||
};
|
||||
_mtt.prepareTagsStr = prepareTagsStr;
|
||||
|
||||
function prepareTagsClass(ids)
|
||||
function prepareDomClassOfTags(ids)
|
||||
{
|
||||
if(!ids || ids == '') return '';
|
||||
var a = ids.split(',');
|
||||
|
|
@ -1037,7 +1043,7 @@ function prepareTagsClass(ids)
|
|||
}
|
||||
return ' '+a.join(' ');
|
||||
};
|
||||
_mtt.prepareTagsClass = prepareTagsClass;
|
||||
_mtt.prepareDomClassOfTags = prepareDomClassOfTags;
|
||||
|
||||
function prepareDueDate(item)
|
||||
{
|
||||
|
|
@ -1456,7 +1462,7 @@ function saveTaskNote(id)
|
|||
var item = json.list[0];
|
||||
taskList[id].note = item.note;
|
||||
taskList[id].noteText = item.noteText;
|
||||
$('#tasknote'+id+'>span').html(prepareHtml(item.note));
|
||||
$('#tasknote'+id).html(prepareTaskNoteInlineHtml(item.note));
|
||||
if(item.note == '') $('#taskrow_'+id).removeClass('task-has-note task-expanded');
|
||||
else $('#taskrow_'+id).addClass('task-has-note task-expanded');
|
||||
cancelTaskNote(id);
|
||||
|
|
|
|||
Loading…
Reference in a new issue