Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editor Paste / Drag-drop Image Handler #4359

Open
wants to merge 16 commits into
base: feature
Choose a base branch
from
Open
56 changes: 16 additions & 40 deletions admin/inc/class_page.php
Original file line number Diff line number Diff line change
Expand Up @@ -1046,50 +1046,26 @@ function build_codebuttons_editor($bind, $editor_language, $smilies)
$code = "code,php,";
}

if($mybb->user['sourceeditor'] == 1)
{
$sourcemode = "MyBBEditor.sourceMode(true);";
}

return <<<EOF

<script type="text/javascript">
var partialmode = {$mybb->settings['partialmode']},
opt_editor = {
plugins: "undo",
format: "bbcode",
bbcodeTrim: true,
style: "../jscripts/sceditor/styles/jquery.sceditor.mybb.css",
rtl: {$lang->settings['rtl']},
locale: "mybblang",
enablePasteFiltering: true,
autoUpdate: true,
emoticonsEnabled: {$emoticons_enabled},
emoticons: {
// Emoticons to be included in the dropdown
dropdown: {
{$dropdownsmilies}
},
// Emoticons to be included in the more section
more: {
{$moresmilies}
var editorElm = "#{$bind}",
sourceMode = {$mybb->user['sourceeditor']},
partialMode = {$mybb->settings['partialmode']},
editorLang = {$editor_language},
postEmbed = { enabled: {$mybb->settings['postembed']}, host: "{$mybb->settings['postembedhost']}", clientKey: "{$mybb->settings['postembedkey']}" },
optEditor = {
style: "../jscripts/sceditor/styles/jquery.sceditor.mybb.css",
rtl: {$lang->settings['rtl']},
emoticonsEnabled: {$emoticons_enabled},
emoticons: {
dropdown: { {$dropdownsmilies} }, // Emoticons to be included in the dropdown
more: { {$moresmilies} }, // Emoticons to be included in the more section
hidden: { {$hiddensmilies} } // Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases
},
// Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases
hidden: {
{$hiddensmilies}
}
},
emoticonsCompat: true,
toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source",
};
{$editor_language}
$(function() {
$("#{$bind}").sceditor(opt_editor);

MyBBEditor = $("#{$bind}").sceditor("instance");
{$sourcemode}
});
toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source"
};
</script>
<script type="text/javascript" src="../jscripts/editor.js?ver=1827"></script>
EOF;
}
}
Expand Down
3 changes: 3 additions & 0 deletions admin/modules/config/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,9 @@ function print_setting_peekers()
'new Peeker($(".setting_pmsallowmycode"), $("#row_setting_pmsallowimgcode, #row_setting_pmsallowvideocode"), 1, true)',
'new Peeker($(".setting_enableshowteam"), $("#row_setting_showaddlgroups, #row_setting_showgroupleaders"), 1, true)',
'new Peeker($(".setting_usereferrals"), $("#row_setting_referralsperpage"), 1, true)',
'new Peeker($(".setting_postembed"), $("#row_setting_postembedhost"), 1, true)',
'new Peeker($("#setting_postembedhost"), $("#row_setting_postembedkey"), /^(img)/, false)',
'new Peeker($("#setting_postembedhost"), $("#row_setting_postembedpath"), /local/, false)',
);

$peekers = $plugins->run_hooks("admin_settings_print_peekers", $peekers);
Expand Down
20 changes: 20 additions & 0 deletions admin/modules/tools/system_health.php
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,21 @@
++$errors;
}

$postembedpath = $mybb->settings['postembedpath'];
if(my_substr($postembedpath, 0, 1) == '.')
{
$postembedpath = MYBB_ROOT . $mybb->settings['postembedpath'];
}
if(is_writable($postembedpath))
{
$message_postembed = "<span style=\"color: green;\">{$lang->writable}</span>";
}
else
{
$message_postembed = "<strong><span style=\"color: #C00\">{$lang->not_writable}</span></strong><br />{$lang->please_chmod_777}";
++$errors;
}

if(is_writable(MYBB_ROOT.'inc/languages/'))
{
$message_language = "<span style=\"color: green;\">{$lang->writable}</span>";
Expand Down Expand Up @@ -953,6 +968,11 @@
$table->construct_cell($message_avatar);
$table->construct_row();

$table->construct_cell("<strong>{$lang->postembed_upload_dir}</strong>");
$table->construct_cell($mybb->settings['postembedpath']);
$table->construct_cell($message_postembed);
$table->construct_row();

$table->construct_cell("<strong>{$lang->language_files}</strong>");
$table->construct_cell("./inc/languages");
$table->construct_cell($message_language);
Expand Down
4 changes: 2 additions & 2 deletions admin/modules/user/users.php
Original file line number Diff line number Diff line change
Expand Up @@ -943,8 +943,8 @@

<link rel="stylesheet" href="../jscripts/sceditor/themes/mybb.css" type="text/css" media="all" />
<script type="text/javascript" src="../jscripts/sceditor/jquery.sceditor.bbcode.min.js?ver=1822"></script>
<script type="text/javascript" src="../jscripts/bbcodes_sceditor.js?ver=1827"></script>
<script type="text/javascript" src="../jscripts/sceditor/plugins/undo.js?ver=1805"></script>
<script type="text/javascript" src="../jscripts/sceditor/plugins/undo.js?ver=1821"></script>
<script type="text/javascript" src="../jscripts/sceditor/plugins/dragdrop.js?ver=1827"></script>
EOF;
$page->output_header($lang->edit_user);

Expand Down
11 changes: 3 additions & 8 deletions inc/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -3443,7 +3443,7 @@ function build_mycode_inserter($bind="message", $smilies = true)
"editor_php" => "PHP",
"editor_maximize" => "Maximize"
);
$editor_language = "(function ($) {\n$.sceditor.locale[\"mybblang\"] = {\n";
$editor_language = "{\n";

$editor_lang_strings = $plugins->run_hooks("mycode_add_codebuttons", $editor_lang_strings);

Expand All @@ -3454,7 +3454,7 @@ function build_mycode_inserter($bind="message", $smilies = true)
$i++;
$js_lang_string = str_replace("\"", "\\\"", $key);
$string = str_replace("\"", "\\\"", $lang->$lang_string);
$editor_language .= "\t\"{$js_lang_string}\": \"{$string}\"";
$editor_language .= "\t\t\"{$js_lang_string}\": \"{$string}\"";

if($i < $editor_languages_count)
{
Expand All @@ -3464,7 +3464,7 @@ function build_mycode_inserter($bind="message", $smilies = true)
$editor_language .= "\n";
}

$editor_language .= "}})(jQuery);";
$editor_language .= "\t}";

if(defined("IN_ADMINCP"))
{
Expand Down Expand Up @@ -3594,11 +3594,6 @@ function build_mycode_inserter($bind="message", $smilies = true)
$code = "code,php,";
}

if($mybb->user['sourceeditor'] == 1)
{
$sourcemode = "MyBBEditor.sourceMode(true);";
}

eval("\$codeinsert = \"".$templates->get("codebuttons")."\";");
}
}
Expand Down
1 change: 1 addition & 0 deletions inc/languages/english/admin/global.lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@
$l['task_promotions_ran'] = "The promotions task successfully ran.";
$l['task_threadviews_ran'] = "The thread views task successfully ran.";
$l['task_usercleanup_ran'] = "The user cleanup task successfully ran.";
$l['task_postembedscleanup_ran'] = "The orphan post embed images cleanup task successfully ran.";
$l['task_massmail_ran'] = "The mass mail task successfully ran.";
$l['task_userpruning_ran'] = "The user pruning task successfully ran.";
$l['task_delayedmoderation_ran'] = "The delayed moderation task successfully ran.";
Expand Down
1 change: 1 addition & 0 deletions inc/languages/english/admin/tools_system_health.lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
$l['config_file'] = "Configuration File";
$l['file_upload_dir'] = "File Uploads Directory";
$l['avatar_upload_dir'] = "Avatar Uploads Directory";
$l['postembed_upload_dir'] = "Post Embed Images Uploads Directory";
$l['language_files'] = "Language Files";
$l['backup_dir'] = "Backups Directory";
$l['cache_dir'] = "Cache Directory";
Expand Down
1 change: 1 addition & 0 deletions inc/languages/english/global.lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@
$l['task_promotions_ran'] = "The promotions task successfully ran.";
$l['task_threadviews_ran'] = "The thread views task successfully ran.";
$l['task_usercleanup_ran'] = "The user cleanup task successfully ran.";
$l['task_postembedscleanup_ran'] = "The orphan post embed images cleanup task successfully ran.";
$l['task_massmail_ran'] = "The mass mail task successfully ran.";
$l['task_userpruning_ran'] = "The user pruning task successfully ran.";
$l['task_delayedmoderation_ran'] = "The delayed moderation task successfully ran.";
Expand Down
37 changes: 37 additions & 0 deletions inc/tasks/postembedscleanup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/**
* MyBB 1.8
* Copyright 2021 MyBB Group, All Rights Reserved
*
* Website: http://www.mybb.com
* License: http://www.mybb.com/about/license
*
*/

function task_postembedscleanup($task)
{
global $mybb, $db, $lang, $plugins;

$dir = trim($mybb->settings['postembedpath'], './');
$files = glob(MYBB_ROOT."{$dir}/*.{jpg,jpeg,png}", GLOB_BRACE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this be problematic for large amount of files? Will the task always fulfill properly regardless of the amount of images? I'm a little surprised by the lack of a database table to control uploaded images, which limits the addition of some ACP interface to manage these unless, for example, being somehow merged with the current attachments tools later on.

Copy link
Member Author

@effone effone May 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern is correct at I have not done a performance benchmarking.
Am open to accept any suggestion to improve this. I also felt the necessity of a dedicated table for upload entries. Didn't follow that way as that can be considered as Big Change leading to rejection of this PR.


if(is_object($plugins))
{
$args = array(
'task' => &$task,
'files' => $files,
);
$plugins->run_hooks('task_postembedscleanup', $args);
}

foreach ($files as $file)
{
$link = str_replace(MYBB_ROOT, $mybb->settings['bburl'] . '/', $file);
$query = $db->simple_select("posts", "COUNT(DISTINCT pid) AS postcount", "message like '%[img%]{$link}[/img]%'");
if (!$db->fetch_field($query, 'postcount'))
{
@unlink($file);
}
}
add_task_log($task, $lang->task_postembedscleanup_ran);
}
20 changes: 19 additions & 1 deletion install/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -1209,8 +1209,26 @@ function requirements_check()
@unlink(MYBB_ROOT.'uploads/avatars/test.write');
}

// Check postembed image directory is writable
$postembedswritable = @fopen(MYBB_ROOT.'uploads/postembeds/test.write', 'w');
if(!$postembedswritable)
{
$errors[] = $lang->sprintf($lang->req_step_error_box, $lang->req_step_error_postembeddir);
$postembedsstatus = $lang->sprintf($lang->req_step_span_fail, $lang->not_writable);
$showerror = 1;
@fclose($postembedswritable);
}
else
{
$postembedsstatus = $lang->sprintf($lang->req_step_span_pass, $lang->writable);
@fclose($postembedswritable);
@my_chmod(MYBB_ROOT.'uploads/postembeds', '0777');
@my_chmod(MYBB_ROOT.'uploads/postembeds/test.write', '0777');
@unlink(MYBB_ROOT.'uploads/postembeds/test.write');
}

// Output requirements page
echo $lang->sprintf($lang->req_step_reqtable, $phpversion, $dbsupportlist, $mbstatus, $xmlstatus, $configstatus, $settingsstatus, $cachestatus, $uploadsstatus, $avatarsstatus);
echo $lang->sprintf($lang->req_step_reqtable, $phpversion, $dbsupportlist, $mbstatus, $xmlstatus, $configstatus, $settingsstatus, $cachestatus, $uploadsstatus, $avatarsstatus, $postembedsstatus);

if($showerror == 1)
{
Expand Down
7 changes: 6 additions & 1 deletion install/resources/language.lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,14 @@
<td class="first">File Uploads Directory Writable:</td>
<td class="last alt_col">{8}</td>
</tr>
<tr class="last">
<tr class="alt_row">
<td class="first">Avatar Uploads Directory Writable:</td>
<td class="last alt_col">{9}</td>
</tr>
<tr class="last">
<td class="first">Post Embed Images Uploads Directory Writable:</td>
<td class="last alt_col">{10}</td>
</tr>
</tbody>
</table>
</div>';
Expand All @@ -148,6 +152,7 @@
$l['req_step_error_cachedir'] = 'The cache directory (cache/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank" rel="noopener">chmod</a> permissions to allow it to be written to.';
$l['req_step_error_uploaddir'] = 'The uploads directory (uploads/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank" rel="noopener">chmod</a> permissions to allow it to be written to.';
$l['req_step_error_avatardir'] = 'The avatars directory (uploads/avatars/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank" rel="noopener">chmod</a> permissions to allow it to be written to.';
$l['req_step_error_postembeddir'] = 'The post embed images upload directory (uploads/postembeds/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank" rel="noopener">chmod</a> permissions to allow it to be written to.';
$l['req_step_error_cssddir'] = 'The css directory (css/) is not writable. Please adjust the <a href="https://docs.mybb.com/1.8/administration/security/file-permissions" target="_blank" rel="noopener">chmod</a> permissions to allow it to be written to.';
$l['req_step_error_tablelist'] = '<div class="error">
<h3>Error</h3>
Expand Down
55 changes: 18 additions & 37 deletions install/resources/mybb_theme.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14161,46 +14161,27 @@ if(use_xmlhttprequest == "1")
</tr>]]></template>
<template name="codebuttons" version="1827"><![CDATA[<link rel="stylesheet" href="{$mybb->asset_url}/jscripts/sceditor/themes/{$theme['editortheme']}" type="text/css" media="all" />
<script type="text/javascript" src="{$mybb->asset_url}/jscripts/sceditor/jquery.sceditor.bbcode.min.js?ver=1822"></script>
<script type="text/javascript" src="{$mybb->asset_url}/jscripts/bbcodes_sceditor.js?ver=1827"></script>
<script type="text/javascript" src="{$mybb->asset_url}/jscripts/sceditor/plugins/undo.js?ver=1821"></script>
<script type="text/javascript" src="{$mybb->asset_url}/jscripts/sceditor/plugins/dragdrop.js?ver=1827"></script>
<script type="text/javascript">
var partialmode = {$mybb->settings['partialmode']},
opt_editor = {
plugins: "undo",
format: "bbcode",
bbcodeTrim: false,
style: "{$mybb->asset_url}/jscripts/sceditor/styles/jquery.sceditor.{$theme['editortheme']}?ver=1823",
rtl: {$lang->settings['rtl']},
locale: "mybblang",
width: "100%",
enablePasteFiltering: true,
autoUpdate: true,
emoticonsEnabled: {$emoticons_enabled},
emoticons: {
// Emoticons to be included in the dropdown
dropdown: {
{$dropdownsmilies}
var editorElm = "#{$bind}",
sourceMode = {$mybb->user['sourceeditor']},
partialMode = {$mybb->settings['partialmode']},
editorLang = {$editor_language},
postEmbed = { enabled: {$mybb->settings['postembed']}, host: "{$mybb->settings['postembedhost']}", clientKey: "{$mybb->settings['postembedkey']}" },
optEditor = {
style: "{$mybb->asset_url}/jscripts/sceditor/styles/jquery.sceditor.{$theme['editortheme']}?ver=1823",
rtl: {$lang->settings['rtl']},
emoticonsEnabled: {$emoticons_enabled},
emoticons: {
dropdown: { {$dropdownsmilies} }, // Emoticons to be included in the dropdown
more: { {$moresmilies} }, // Emoticons to be included in the more section
hidden: { {$hiddensmilies} } // Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases
},
// Emoticons to be included in the more section
more: {
{$moresmilies}
},
// Emoticons that are not shown in the dropdown but will still be converted. Can be used for things like aliases
hidden: {
{$hiddensmilies}
}
},
emoticonsCompat: true,
toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source",
};
{$editor_language}
$(function() {
$("#{$bind}").sceditor(opt_editor);

MyBBEditor = $("#{$bind}").sceditor("instance");
{$sourcemode}
});
</script>]]></template>
toolbar: "{$basic1}{$align}{$font}{$size}{$color}{$removeformat}{$basic2}image,{$email}{$link}|video{$emoticon}|{$list}{$code}quote|maximize,source"
};
</script>
<script type="text/javascript" src="{$mybb->asset_url}/jscripts/editor.js?ver=1827"></script>]]></template>
<template name="contact" version="1827"><![CDATA[<html>
<head>
<title>{$mybb->settings['bbname']} - {$lang->contact}</title>
Expand Down
36 changes: 36 additions & 0 deletions install/resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,42 @@ min=0]]></optionscode>
<settingvalue><![CDATA[0]]></settingvalue>
<isdefault>1</isdefault>
</setting>
<setting name="postembed">
<title>Handle Pasting / Dropping Images in Editor</title>
<description><![CDATA[If enabled the image data / files pasted or dropped in editor will be uploaded as image to embed in post.]]></description>
<disporder>25</disporder>
<optionscode><![CDATA[yesno]]></optionscode>
<settingvalue><![CDATA[1]]></settingvalue>
<isdefault>1</isdefault>
</setting>
<setting name="postembedhost">
<title>Post Embed Image Host</title>
<description><![CDATA[Select where to upload the images pasted or dropped in editor.]]></description>
<disporder>26</disporder>
<optionscode><![CDATA[select
local=Upload locally
imgur=Upload to Imgur
imgbb=Upload to ImgBB
]]></optionscode>
<settingvalue><![CDATA[local]]></settingvalue>
<isdefault>1</isdefault>
</setting>
<setting name="postembedkey">
<title>Image Host Client ID</title>
<description><![CDATA[Enter your client ID obtained from host to use image upload API. Leaving this field blank will fallback to local image upload.]]></description>
<disporder>27</disporder>
<optionscode><![CDATA[text]]></optionscode>
<settingvalue><![CDATA[]]></settingvalue>
<isdefault>1</isdefault>
</setting>
<setting name="postembedpath">
<title>Post Embeds Upload Path</title>
<description><![CDATA[Specify the path where you want your post embed image files to be uploaded (<b>must be CHMOD 777</b> and a relative path under domain root for upload and embed to work).]]></description>
<disporder>28</disporder>
<optionscode><![CDATA[text]]></optionscode>
<settingvalue><![CDATA[./uploads/postembeds]]></settingvalue>
<isdefault>1</isdefault>
</setting>
</settinggroup>
<settinggroup name="attachments" title="Attachments" description="Various options related to the attachment system can be managed and set here." disporder="12" isdefault="1">
<setting name="enableattachments">
Expand Down