| 
									
										
										
										
											2015-04-20 17:56:43 -04:00
										 |  |  | 'use strict'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 11:20:53 +03:00
										 |  |  | var nconf = require('nconf'); | 
					
						
							|  |  |  | var url = require('url'); | 
					
						
							|  |  |  | var winston = require('winston'); | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | const sanitize = require('sanitize-html'); | 
					
						
							|  |  |  | const _ = require('lodash'); | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | var meta = require('../meta'); | 
					
						
							| 
									
										
										
										
											2016-02-23 13:08:38 +02:00
										 |  |  | var plugins = require('../plugins'); | 
					
						
							| 
									
										
										
										
											2017-04-08 20:22:21 -06:00
										 |  |  | var translator = require('../translator'); | 
					
						
							| 
									
										
										
										
											2017-10-13 21:02:41 -06:00
										 |  |  | var utils = require('../utils'); | 
					
						
							| 
									
										
										
										
											2015-04-20 17:56:43 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | let sanitizeConfig = { | 
					
						
							|  |  |  | 	allowedTags: sanitize.defaults.allowedTags.concat([ | 
					
						
							|  |  |  | 		// Some safe-to-use tags to add
 | 
					
						
							| 
									
										
										
										
											2020-09-29 13:34:24 -04:00
										 |  |  | 		'sup', 'ins', 'del', 'img', 'button', | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | 		'video', 'audio', 'iframe', 'embed', | 
					
						
							| 
									
										
										
										
											2020-09-29 13:34:24 -04:00
										 |  |  | 		// 'sup' still necessary until https://github.com/apostrophecms/sanitize-html/pull/422 merged
 | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | 	]), | 
					
						
							|  |  |  | 	allowedAttributes: { | 
					
						
							|  |  |  | 		...sanitize.defaults.allowedAttributes, | 
					
						
							| 
									
										
										
										
											2020-09-29 13:34:24 -04:00
										 |  |  | 		a: ['href', 'name', 'hreflang', 'media', 'rel', 'target', 'type'], | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | 		img: ['alt', 'height', 'ismap', 'src', 'usemap', 'width', 'srcset'], | 
					
						
							|  |  |  | 		iframe: ['height', 'name', 'src', 'width'], | 
					
						
							|  |  |  | 		video: ['autoplay', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'], | 
					
						
							|  |  |  | 		audio: ['autoplay', 'controls', 'loop', 'muted', 'preload', 'src'], | 
					
						
							|  |  |  | 		embed: ['height', 'src', 'type', 'width'], | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	globalAttributes: ['accesskey', 'class', 'contenteditable', 'dir', | 
					
						
							|  |  |  | 		'draggable', 'dropzone', 'hidden', 'id', 'lang', 'spellcheck', 'style', | 
					
						
							|  |  |  | 		'tabindex', 'title', 'translate', 'aria-expanded', 'data-*', | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2019-12-07 12:37:10 -07:00
										 |  |  | 	allowedClasses: { | 
					
						
							|  |  |  | 		...sanitize.defaults.allowedClasses, | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-13 11:43:39 +02:00
										 |  |  | module.exports = function (Posts) { | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 	Posts.urlRegex = { | 
					
						
							|  |  |  | 		regex: /href="([^"]+)"/g, | 
					
						
							|  |  |  | 		length: 6, | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2017-05-28 01:26:56 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 	Posts.imgRegex = { | 
					
						
							| 
									
										
										
										
											2017-05-28 01:26:56 -04:00
										 |  |  | 		regex: /src="([^"]+)"/g, | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 		length: 5, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 	Posts.parsePost = async function (postData) { | 
					
						
							| 
									
										
										
										
											2018-10-21 19:33:46 -04:00
										 |  |  | 		if (!postData) { | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 			return postData; | 
					
						
							| 
									
										
										
										
											2018-10-21 19:33:46 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-09 19:52:48 +03:00
										 |  |  | 		postData.content = String(postData.content || ''); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 		const cache = require('./cache'); | 
					
						
							|  |  |  | 		const pid = String(postData.pid); | 
					
						
							|  |  |  | 		const cachedContent = cache.get(pid); | 
					
						
							|  |  |  | 		if (postData.pid && cachedContent !== undefined) { | 
					
						
							|  |  |  | 			postData.content = cachedContent; | 
					
						
							| 
									
										
										
										
											2018-10-15 15:03:06 -04:00
										 |  |  | 			cache.hits += 1; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 			return postData; | 
					
						
							| 
									
										
										
										
											2015-04-20 17:56:43 -04:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-10-15 15:03:06 -04:00
										 |  |  | 		cache.misses += 1; | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 		const data = await plugins.fireHook('filter:parse.post', { postData: postData }); | 
					
						
							|  |  |  | 		data.postData.content = translator.escape(data.postData.content); | 
					
						
							|  |  |  | 		if (global.env === 'production' && data.postData.pid) { | 
					
						
							|  |  |  | 			cache.set(pid, data.postData.content); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return data.postData; | 
					
						
							| 
									
										
										
										
											2015-04-20 17:56:43 -04:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 	Posts.parseSignature = async function (userData, uid) { | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 		userData.signature = sanitizeSignature(userData.signature || ''); | 
					
						
							| 
									
										
										
										
											2019-07-17 19:05:55 -04:00
										 |  |  | 		return await plugins.fireHook('filter:parse.signature', { userData: userData, uid: uid }); | 
					
						
							| 
									
										
										
										
											2015-04-20 17:56:43 -04:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 	Posts.relativeToAbsolute = function (content, regex) { | 
					
						
							| 
									
										
										
										
											2020-09-03 12:02:07 -04:00
										 |  |  | 		// Turns relative links in content to absolute urls
 | 
					
						
							|  |  |  | 		if (!content) { | 
					
						
							|  |  |  | 			return content; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-17 20:20:42 -07:00
										 |  |  | 		var parsed; | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 		var current = regex.regex.exec(content); | 
					
						
							| 
									
										
										
										
											2017-02-17 20:20:42 -07:00
										 |  |  | 		var absolute; | 
					
						
							| 
									
										
										
										
											2017-02-18 13:51:26 -07:00
										 |  |  | 		while (current !== null) { | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 			if (current[1]) { | 
					
						
							| 
									
										
										
										
											2016-06-03 11:20:53 +03:00
										 |  |  | 				try { | 
					
						
							|  |  |  | 					parsed = url.parse(current[1]); | 
					
						
							|  |  |  | 					if (!parsed.protocol) { | 
					
						
							|  |  |  | 						if (current[1].startsWith('/')) { | 
					
						
							|  |  |  | 							// Internal link
 | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 							absolute = nconf.get('base_url') + current[1]; | 
					
						
							| 
									
										
										
										
											2016-06-03 11:20:53 +03:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 							// External link
 | 
					
						
							|  |  |  | 							absolute = '//' + current[1]; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 						content = content.slice(0, current.index + regex.length) + absolute + content.slice(current.index + regex.length + current[1].length); | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-02-18 01:52:56 -07:00
										 |  |  | 				} catch (err) { | 
					
						
							| 
									
										
										
										
											2016-06-29 21:09:05 +03:00
										 |  |  | 					winston.verbose(err.messsage); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-05-28 01:10:16 -04:00
										 |  |  | 			current = regex.regex.exec(content); | 
					
						
							| 
									
										
										
										
											2016-05-16 08:22:23 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return content; | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | 	Posts.sanitize = function (content) { | 
					
						
							|  |  |  | 		return sanitize(content, { | 
					
						
							| 
									
										
										
										
											2019-12-07 12:37:10 -07:00
										 |  |  | 			allowedTags: sanitizeConfig.allowedTags, | 
					
						
							|  |  |  | 			allowedAttributes: sanitizeConfig.allowedAttributes, | 
					
						
							|  |  |  | 			allowedClasses: sanitizeConfig.allowedClasses, | 
					
						
							| 
									
										
										
										
											2019-08-30 14:40:11 -04:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 11:42:49 -04:00
										 |  |  | 	Posts.configureSanitize = async () => { | 
					
						
							|  |  |  | 		// Each allowed tags should have some common global attributes...
 | 
					
						
							|  |  |  | 		sanitizeConfig.allowedTags.forEach((tag) => { | 
					
						
							|  |  |  | 			sanitizeConfig.allowedAttributes[tag] = _.union(sanitizeConfig.allowedAttributes[tag], sanitizeConfig.globalAttributes); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 11:44:04 -04:00
										 |  |  | 		// Some plugins might need to adjust or whitelist their own tags...
 | 
					
						
							| 
									
										
										
										
											2019-09-04 11:42:49 -04:00
										 |  |  | 		sanitizeConfig = await plugins.fireHook('filter:sanitize.config', sanitizeConfig); | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 	function sanitizeSignature(signature) { | 
					
						
							| 
									
										
										
										
											2017-04-13 12:37:54 -06:00
										 |  |  | 		signature = translator.escape(signature); | 
					
						
							| 
									
										
										
										
											2017-02-17 20:20:42 -07:00
										 |  |  | 		var tagsToStrip = []; | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-21 16:47:51 -04:00
										 |  |  | 		if (meta.config['signatures:disableLinks']) { | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 			tagsToStrip.push('a'); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-21 16:47:51 -04:00
										 |  |  | 		if (meta.config['signatures:disableImages']) { | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 			tagsToStrip.push('img'); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-13 21:02:41 -06:00
										 |  |  | 		return utils.stripHTMLTags(signature, tagsToStrip); | 
					
						
							| 
									
										
										
										
											2016-11-21 11:07:20 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-26 23:34:55 -05:00
										 |  |  | }; |