parent
1d177d9689
commit
146e7ca4b1
22 changed files with 8516 additions and 14 deletions
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<module type="WEB_MODULE" version="4"> |
||||||
|
<component name="NewModuleRootManager"> |
||||||
|
<content url="file://$MODULE_DIR$" /> |
||||||
|
<orderEntry type="inheritedJdk" /> |
||||||
|
<orderEntry type="sourceFolder" forTests="false" /> |
||||||
|
</component> |
||||||
|
</module> |
@ -0,0 +1,4 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="Encoding" addBOMForNewFiles="with NO BOM" /> |
||||||
|
</project> |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="ProjectModuleManager"> |
||||||
|
<modules> |
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/LoveKKComment.iml" filepath="$PROJECT_DIR$/.idea/LoveKKComment.iml" /> |
||||||
|
</modules> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,8 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="PhpIncludePathManager"> |
||||||
|
<include_path> |
||||||
|
<path value="$PROJECT_DIR$/../../../v1.1" /> |
||||||
|
</include_path> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,333 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project version="4"> |
||||||
|
<component name="ChangeListManager"> |
||||||
|
<list default="true" id="32f10aeb-a6c7-469b-832d-e86fea59b938" name="默认的" comment="" /> |
||||||
|
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> |
||||||
|
<option name="SHOW_DIALOG" value="false" /> |
||||||
|
<option name="HIGHLIGHT_CONFLICTS" value="true" /> |
||||||
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> |
||||||
|
<option name="LAST_RESOLUTION" value="IGNORE" /> |
||||||
|
</component> |
||||||
|
<component name="FileEditorManager"> |
||||||
|
<leaf> |
||||||
|
<file pinned="false" current-in-tab="false"> |
||||||
|
<entry file="file://$PROJECT_DIR$/Plugin.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="254"> |
||||||
|
<caret line="910" column="31" selection-start-line="910" selection-start-column="31" selection-end-line="910" selection-end-column="31" /> |
||||||
|
<folding> |
||||||
|
<element signature="e#6#134#0#PHP" expanded="true" /> |
||||||
|
</folding> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
</file> |
||||||
|
<file pinned="false" current-in-tab="false"> |
||||||
|
<entry file="file://$PROJECT_DIR$/Action.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="-7130"> |
||||||
|
<caret line="212" column="27" selection-start-line="212" selection-start-column="27" selection-end-line="212" selection-end-column="27" /> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
</file> |
||||||
|
<file pinned="false" current-in-tab="true"> |
||||||
|
<entry file="file://$PROJECT_DIR$/README.md"> |
||||||
|
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]"> |
||||||
|
<state split_layout="FIRST"> |
||||||
|
<first_editor relative-caret-position="553"> |
||||||
|
<caret line="60" column="13" selection-start-line="60" selection-start-column="13" selection-end-line="60" selection-end-column="13" /> |
||||||
|
</first_editor> |
||||||
|
<second_editor /> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
</file> |
||||||
|
</leaf> |
||||||
|
</component> |
||||||
|
<component name="FileTemplateManagerImpl"> |
||||||
|
<option name="RECENT_TEMPLATES"> |
||||||
|
<list> |
||||||
|
<option value="HTML File" /> |
||||||
|
</list> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
<component name="FindInProjectRecents"> |
||||||
|
<findStrings> |
||||||
|
<find>smtp_auth</find> |
||||||
|
<find>OAuth</find> |
||||||
|
<find>PHPMailer</find> |
||||||
|
<find>send(</find> |
||||||
|
<find>_e</find> |
||||||
|
<find>_e(</find> |
||||||
|
<find>getServerExtList</find> |
||||||
|
<find>server_caps</find> |
||||||
|
<find>hello(</find> |
||||||
|
<find>Hostname</find> |
||||||
|
<find>Helo</find> |
||||||
|
<find>serverHostname</find> |
||||||
|
<find>begin</find> |
||||||
|
<find>file_put</find> |
||||||
|
<find>file_put_contents</find> |
||||||
|
<find>widgetB</find> |
||||||
|
<find>Helper::widgetById</find> |
||||||
|
</findStrings> |
||||||
|
<replaceStrings> |
||||||
|
<replace>self::getWidget</replace> |
||||||
|
</replaceStrings> |
||||||
|
</component> |
||||||
|
<component name="Git.Settings"> |
||||||
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." /> |
||||||
|
</component> |
||||||
|
<component name="IdeDocumentHistory"> |
||||||
|
<option name="CHANGED_PATHS"> |
||||||
|
<list> |
||||||
|
<option value="$PROJECT_DIR$/theme/forget.html" /> |
||||||
|
<option value="$PROJECT_DIR$/Plugin.php" /> |
||||||
|
<option value="$PROJECT_DIR$/Action.php" /> |
||||||
|
<option value="$PROJECT_DIR$/README.md" /> |
||||||
|
</list> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
<component name="PhpWorkspaceProjectConfiguration"> |
||||||
|
<include_path> |
||||||
|
<path value="$PROJECT_DIR$/../../../v1.1" /> |
||||||
|
</include_path> |
||||||
|
</component> |
||||||
|
<component name="ProjectFrameBounds" extendedState="6"> |
||||||
|
<option name="x" value="-6" /> |
||||||
|
<option name="y" value="505" /> |
||||||
|
<option name="width" value="1693" /> |
||||||
|
<option name="height" value="515" /> |
||||||
|
</component> |
||||||
|
<component name="ProjectLevelVcsManager" settingsEditedManually="true" /> |
||||||
|
<component name="ProjectView"> |
||||||
|
<navigator proportions="" version="1"> |
||||||
|
<foldersAlwaysOnTop value="true" /> |
||||||
|
</navigator> |
||||||
|
<panes> |
||||||
|
<pane id="Scope" /> |
||||||
|
<pane id="ProjectPane"> |
||||||
|
<subPane> |
||||||
|
<expand> |
||||||
|
<path> |
||||||
|
<item name="LoveKKComment" type="b2602c69:ProjectViewProjectNode" /> |
||||||
|
<item name="LoveKKComment" type="462c0819:PsiDirectoryNode" /> |
||||||
|
</path> |
||||||
|
<path> |
||||||
|
<item name="LoveKKComment" type="b2602c69:ProjectViewProjectNode" /> |
||||||
|
<item name="External Libraries" type="bcb0276e:PhpExternalLibrariesNodePatcher$PatchedExternalLibrariesNode" /> |
||||||
|
</path> |
||||||
|
</expand> |
||||||
|
<select /> |
||||||
|
</subPane> |
||||||
|
</pane> |
||||||
|
</panes> |
||||||
|
</component> |
||||||
|
<component name="PropertiesComponent"> |
||||||
|
<property name="DefaultHtmlFileTemplate" value="HTML File" /> |
||||||
|
<property name="HbShouldOpenHtmlAsHb" value="" /> |
||||||
|
<property name="WebServerToolWindowFactoryState" value="false" /> |
||||||
|
<property name="last_opened_file_path" value="$PROJECT_DIR$/../../../v1.1" /> |
||||||
|
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" /> |
||||||
|
<property name="settings.editor.selected.configurable" value="project.propVCSSupport.Mappings" /> |
||||||
|
</component> |
||||||
|
<component name="RunDashboard"> |
||||||
|
<option name="ruleStates"> |
||||||
|
<list> |
||||||
|
<RuleState> |
||||||
|
<option name="name" value="ConfigurationTypeDashboardGroupingRule" /> |
||||||
|
</RuleState> |
||||||
|
<RuleState> |
||||||
|
<option name="name" value="StatusDashboardGroupingRule" /> |
||||||
|
</RuleState> |
||||||
|
</list> |
||||||
|
</option> |
||||||
|
</component> |
||||||
|
<component name="SvnConfiguration"> |
||||||
|
<configuration /> |
||||||
|
</component> |
||||||
|
<component name="TaskManager"> |
||||||
|
<task active="true" id="Default" summary="Default task"> |
||||||
|
<changelist id="32f10aeb-a6c7-469b-832d-e86fea59b938" name="默认的" comment="" /> |
||||||
|
<created>1521955841482</created> |
||||||
|
<option name="number" value="Default" /> |
||||||
|
<option name="presentableId" value="Default" /> |
||||||
|
<updated>1521955841482</updated> |
||||||
|
<workItem from="1521955842856" duration="1419000" /> |
||||||
|
<workItem from="1521969048994" duration="10520000" /> |
||||||
|
<workItem from="1522241522350" duration="2418000" /> |
||||||
|
<workItem from="1534670224207" duration="2361000" /> |
||||||
|
<workItem from="1546824740806" duration="4921000" /> |
||||||
|
<workItem from="1546834601566" duration="4637000" /> |
||||||
|
<workItem from="1546859374707" duration="14218000" /> |
||||||
|
<workItem from="1546912900287" duration="11466000" /> |
||||||
|
<workItem from="1546962005464" duration="877000" /> |
||||||
|
</task> |
||||||
|
<task id="LOCAL-00001" summary="编写中"> |
||||||
|
<created>1521985946437</created> |
||||||
|
<option name="number" value="00001" /> |
||||||
|
<option name="presentableId" value="LOCAL-00001" /> |
||||||
|
<option name="project" value="LOCAL" /> |
||||||
|
<updated>1521985946437</updated> |
||||||
|
</task> |
||||||
|
<task id="LOCAL-00002" summary="1.0.0"> |
||||||
|
<created>1521990347912</created> |
||||||
|
<option name="number" value="00002" /> |
||||||
|
<option name="presentableId" value="LOCAL-00002" /> |
||||||
|
<option name="project" value="LOCAL" /> |
||||||
|
<updated>1521990347912</updated> |
||||||
|
</task> |
||||||
|
<option name="localTasksCounter" value="3" /> |
||||||
|
<servers /> |
||||||
|
</component> |
||||||
|
<component name="TimeTrackingManager"> |
||||||
|
<option name="totallyTimeSpent" value="52837000" /> |
||||||
|
</component> |
||||||
|
<component name="ToolWindowManager"> |
||||||
|
<frame x="-8" y="-8" width="1696" height="1026" extended-state="6" /> |
||||||
|
<editor active="true" /> |
||||||
|
<layout> |
||||||
|
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.14425428" /> |
||||||
|
<window_info id="Structure" order="1" weight="0.25" /> |
||||||
|
<window_info id="Favorites" order="2" side_tool="true" /> |
||||||
|
<window_info anchor="bottom" id="Message" order="0" /> |
||||||
|
<window_info anchor="bottom" id="Find" order="1" /> |
||||||
|
<window_info anchor="bottom" id="Run" order="2" /> |
||||||
|
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" /> |
||||||
|
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> |
||||||
|
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> |
||||||
|
<window_info anchor="bottom" id="TODO" order="6" /> |
||||||
|
<window_info anchor="bottom" id="运行" order="7" /> |
||||||
|
<window_info anchor="bottom" id="Docker" order="8" show_stripe_button="false" /> |
||||||
|
<window_info anchor="bottom" id="Version Control" order="9" show_stripe_button="false" /> |
||||||
|
<window_info anchor="bottom" id="Terminal" order="10" /> |
||||||
|
<window_info anchor="bottom" id="Event Log" order="11" side_tool="true" /> |
||||||
|
<window_info anchor="bottom" id="调试" order="12" /> |
||||||
|
<window_info anchor="bottom" id="消息" order="13" weight="0.3292683" /> |
||||||
|
<window_info anchor="bottom" id="Database Changes" order="14" show_stripe_button="false" /> |
||||||
|
<window_info anchor="right" id="Commander" order="0" weight="0.4" /> |
||||||
|
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> |
||||||
|
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> |
||||||
|
<window_info anchor="right" id="Database" order="3" /> |
||||||
|
</layout> |
||||||
|
</component> |
||||||
|
<component name="TypeScriptGeneratedFilesManager"> |
||||||
|
<option name="version" value="1" /> |
||||||
|
</component> |
||||||
|
<component name="VcsManagerConfiguration"> |
||||||
|
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" /> |
||||||
|
<ignored-roots> |
||||||
|
<path value="$PROJECT_DIR$/.." /> |
||||||
|
<path value="$PROJECT_DIR$" /> |
||||||
|
</ignored-roots> |
||||||
|
<MESSAGE value="编写中" /> |
||||||
|
<MESSAGE value="1.0.0" /> |
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="1.0.0" /> |
||||||
|
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" /> |
||||||
|
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="true" /> |
||||||
|
<option name="REARRANGE_BEFORE_PROJECT_COMMIT" value="true" /> |
||||||
|
</component> |
||||||
|
<component name="editorHistoryManager"> |
||||||
|
<entry file="file://$PROJECT_DIR$/theme/approved.html"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="442"> |
||||||
|
<caret line="17" column="8" selection-start-line="17" selection-start-column="8" selection-end-line="17" selection-end-column="8" /> |
||||||
|
<folding> |
||||||
|
<element signature="n#style#0;n#table#0;n#!!top" expanded="true" /> |
||||||
|
</folding> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/theme/forget.html"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="78"> |
||||||
|
<caret line="3" column="96" selection-start-line="3" selection-start-column="96" selection-end-line="3" selection-end-column="96" /> |
||||||
|
<folding> |
||||||
|
<element signature="n#style#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#div#0;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#h1#0;n#div#0;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#a#0;n#h1#0;n#div#0;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#h2#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#span#0;n#h2#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#p#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#th#0;n#tr#0;n#thead#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#th#1;n#tr#0;n#thead#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#th#2;n#tr#0;n#thead#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#td#0;n#tr#0;n#tbody#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#td#1;n#tr#0;n#tbody#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#td#2;n#tr#0;n#tbody#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#a#0;n#td#2;n#tr#0;n#tbody#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#td#0;n#tr#1;n#tbody#0;n#table#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
<element signature="n#style#0;n#div#0;n#div#1;n#div#0;n#div#0;n#!!top" expanded="true" /> |
||||||
|
</folding> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/lib/SMTP.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="350"> |
||||||
|
<caret line="737" lean-forward="true" selection-start-line="737" selection-end-line="737" /> |
||||||
|
<folding> |
||||||
|
<element signature="e#6#839#0#PHP" expanded="true" /> |
||||||
|
</folding> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/lib/PHPMailer.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="688"> |
||||||
|
<caret line="3599" selection-start-line="3599" selection-end-line="3599" /> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/LICENSE"> |
||||||
|
<provider selected="true" editor-type-id="text-editor" /> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/Plugin.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="254"> |
||||||
|
<caret line="910" column="31" selection-start-line="910" selection-start-column="31" selection-end-line="910" selection-end-column="31" /> |
||||||
|
<folding> |
||||||
|
<element signature="e#6#134#0#PHP" expanded="true" /> |
||||||
|
</folding> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/Action.php"> |
||||||
|
<provider selected="true" editor-type-id="text-editor"> |
||||||
|
<state relative-caret-position="-7130"> |
||||||
|
<caret line="212" column="27" selection-start-line="212" selection-start-column="27" selection-end-line="212" selection-end-column="27" /> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
<entry file="file://$PROJECT_DIR$/README.md"> |
||||||
|
<provider selected="true" editor-type-id="split-provider[text-editor;markdown-preview-editor]"> |
||||||
|
<state split_layout="FIRST"> |
||||||
|
<first_editor relative-caret-position="553"> |
||||||
|
<caret line="60" column="13" selection-start-line="60" selection-start-column="13" selection-end-line="60" selection-end-column="13" /> |
||||||
|
</first_editor> |
||||||
|
<second_editor /> |
||||||
|
</state> |
||||||
|
</provider> |
||||||
|
</entry> |
||||||
|
</component> |
||||||
|
<component name="masterDetails"> |
||||||
|
<states> |
||||||
|
<state key="ScopeChooserConfigurable.UI"> |
||||||
|
<settings> |
||||||
|
<splitter-proportions> |
||||||
|
<option name="proportions"> |
||||||
|
<list> |
||||||
|
<option value="0.2" /> |
||||||
|
</list> |
||||||
|
</option> |
||||||
|
</splitter-proportions> |
||||||
|
</settings> |
||||||
|
</state> |
||||||
|
</states> |
||||||
|
</component> |
||||||
|
</project> |
@ -0,0 +1,513 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Typecho 评论通知、找回密码插件 |
||||||
|
* |
||||||
|
* @package LoveKKComment |
||||||
|
* @author 康粑粑 |
||||||
|
* @version 1.0.5 |
||||||
|
* @link https://www.usebsd.com |
||||||
|
*/ |
||||||
|
|
||||||
|
if ( !defined('__TYPECHO_ROOT_DIR__') ) exit; |
||||||
|
|
||||||
|
class LoveKKComment_Action extends Widget_Abstract_Users implements Widget_Interface_Do |
||||||
|
{ |
||||||
|
/** |
||||||
|
* 插件配置 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* @var mixed |
||||||
|
*/ |
||||||
|
private $_plugin = NULL; |
||||||
|
|
||||||
|
/** |
||||||
|
* 构造函数 |
||||||
|
* |
||||||
|
* @param mixed $request 请求对象 |
||||||
|
* @param mixed $response 输出对象 |
||||||
|
* @param null $params 请求参数 |
||||||
|
* |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
*/ |
||||||
|
public function __construct($request, $response, $params = NULL) |
||||||
|
{ |
||||||
|
parent::__construct($request, $response, $params); |
||||||
|
// 获取插件配置信息 |
||||||
|
$this->_plugin = $this->options->plugin('LoveKKComment'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 找回密码页面输出 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param string $act 当前操作 |
||||||
|
* @param mixed $form 表单对象 |
||||||
|
*/ |
||||||
|
private function html($act = 'forget', $form = NULL) |
||||||
|
{ |
||||||
|
?> |
||||||
|
<!DOCTYPE html> |
||||||
|
<html class="no-js"> |
||||||
|
<head> |
||||||
|
<meta charset="<?php $this->options->charset(); ?>">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||||
|
<meta name="renderer" content="webkit"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||||
|
<title><?php _e('%s - %s - Powered by Typecho', 'reset' == $act ? _t('重置密码') : _t('找回密码'), $this->options->title); ?></title>
|
||||||
|
<meta name="robots" content="noindex, nofollow"> |
||||||
|
<link rel="stylesheet" |
||||||
|
href="<?php $this->options->adminStaticUrl('css', 'normalize.css'); ?>">
|
||||||
|
<link rel="stylesheet" |
||||||
|
href="<?php $this->options->adminStaticUrl('css', 'grid.css'); ?>">
|
||||||
|
<link rel="stylesheet" |
||||||
|
href="<?php $this->options->adminStaticUrl('css', 'style.css'); ?>">
|
||||||
|
<!--[if lt IE 9]> |
||||||
|
<script src="<?php $this->options->adminStaticUrl('js', 'html5shiv.js');?>"></script>
|
||||||
|
<script src="<?php $this->options->adminStaticUrl('js', 'respond.js');?>"></script>
|
||||||
|
<![endif]--> |
||||||
|
</head> |
||||||
|
<body class="body-100"> |
||||||
|
<!--[if lt IE 9]> |
||||||
|
<div class="message error browsehappy" role="dialog"><?php _e('当前网页 <strong>不支持</strong> 你正在使用的浏览器. 为了正常的访问, 请 |
||||||
|
<a href="http://browsehappy.com/">升级你的浏览器</a>'); ?>. |
||||||
|
</div> |
||||||
|
<![endif]--> |
||||||
|
<div class="typecho-login-wrap"> |
||||||
|
<div class="typecho-login"> |
||||||
|
<h1><a href="http://typecho.org" class="i-logo">Typecho</a></h1> |
||||||
|
<?php $form->render(); ?> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<script src="<?php $this->options->adminStaticUrl('js', 'jquery.js'); ?>"></script>
|
||||||
|
<script src="<?php $this->options->adminStaticUrl('js', 'jquery-ui.js'); ?>"></script>
|
||||||
|
<script src="<?php $this->options->adminStaticUrl('js', 'typecho.js'); ?>"></script>
|
||||||
|
<script> |
||||||
|
(function () { |
||||||
|
$(document).ready(function () { |
||||||
|
(function () { |
||||||
|
var prefix = '<?php echo Typecho_Cookie::getPrefix();?>',
|
||||||
|
cookies = { |
||||||
|
notice: $.cookie(prefix + '__typecho_notice'), |
||||||
|
noticeType: $.cookie(prefix + '__typecho_notice_type'), |
||||||
|
highlight: $.cookie(prefix + '__typecho_notice_highlight') |
||||||
|
}, |
||||||
|
path = '<?php echo Typecho_Cookie::getPath(); ?>';
|
||||||
|
if (!!cookies.notice && 'success|notice|error'.indexOf(cookies.noticeType) >= 0) { |
||||||
|
var head = $('.typecho-head-nav'), |
||||||
|
p = $('<div class="message popup ' + cookies.noticeType + '">' |
||||||
|
+ '<ul><li>' + $.parseJSON(cookies.notice).join('</li><li>') |
||||||
|
+ '</li></ul></div>'), offset = 0; |
||||||
|
if (head.length > 0) { |
||||||
|
p.insertAfter(head); |
||||||
|
offset = head.outerHeight(); |
||||||
|
} else { |
||||||
|
p.prependTo(document.body); |
||||||
|
} |
||||||
|
|
||||||
|
function checkScroll() { |
||||||
|
if ($(window).scrollTop() >= offset) { |
||||||
|
p.css({ |
||||||
|
'position': 'fixed', |
||||||
|
'top': 0 |
||||||
|
}); |
||||||
|
} else { |
||||||
|
p.css({ |
||||||
|
'position': 'absolute', |
||||||
|
'top': offset |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$(window).scroll(function () { |
||||||
|
checkScroll(); |
||||||
|
}); |
||||||
|
checkScroll(); |
||||||
|
p.slideDown(function () { |
||||||
|
var t = $(this), color = '#C6D880'; |
||||||
|
if (t.hasClass('error')) { |
||||||
|
color = '#FBC2C4'; |
||||||
|
} else if (t.hasClass('notice')) { |
||||||
|
color = '#FFD324'; |
||||||
|
} |
||||||
|
t.effect('highlight', {color: color}) |
||||||
|
.delay(5000).fadeOut(function () { |
||||||
|
$(this).remove(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
$.cookie(prefix + '__typecho_notice', null, {path: path}); |
||||||
|
$.cookie(prefix + '__typecho_notice_type', null, {path: path}); |
||||||
|
} |
||||||
|
if (cookies.highlight) { |
||||||
|
$('#' + cookies.highlight).effect('highlight', 1000); |
||||||
|
$.cookie(prefix + '__typecho_notice_highlight', null, {path: path}); |
||||||
|
} |
||||||
|
})(); |
||||||
|
(function () { |
||||||
|
$('#typecho-nav-list').find('.parent a').focus(function () { |
||||||
|
$('#typecho-nav-list').find('.child').hide(); |
||||||
|
$(this).parents('.root').find('.child').show(); |
||||||
|
}); |
||||||
|
$('.operate').find('a').focus(function () { |
||||||
|
$('#typecho-nav-list').find('.child').hide(); |
||||||
|
}); |
||||||
|
})(); |
||||||
|
if ($('.typecho-login').length == 0) { |
||||||
|
$('a').each(function () { |
||||||
|
var t = $(this), href = t.attr('href'); |
||||||
|
if ((href && href[0] == '#') |
||||||
|
|| /^<?php echo preg_quote($this->options->adminUrl, '/'); ?>.*$/.exec(href)
|
||||||
|
|| /^<?php echo substr(preg_quote(Typecho_Common::url('s', $this->options->index), '/'), 0, -1); ?>action\/[_a-zA-Z0-9\/]+.*$/.exec(href)) {
|
||||||
|
return; |
||||||
|
} |
||||||
|
t.attr('target', '_blank'); |
||||||
|
}); |
||||||
|
} |
||||||
|
}); |
||||||
|
})(); |
||||||
|
</script> |
||||||
|
<?php if ( 'forget' == $act ) : ?> |
||||||
|
<script>$(document).ready(function () { |
||||||
|
$('#mail').focus(); |
||||||
|
});</script><?php endif; ?> |
||||||
|
</body> |
||||||
|
</html> |
||||||
|
<?php |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 忘记密码表单 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* @return Typecho_Widget_Helper_Form |
||||||
|
*/ |
||||||
|
private function forgetForm() |
||||||
|
{ |
||||||
|
// 创建表单 |
||||||
|
$form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/lovekkcomment'), Typecho_Widget_Helper_Form::POST_METHOD); |
||||||
|
// 邮箱地址 |
||||||
|
$mail = new Typecho_Widget_Helper_Form_Element_Text('mail', NULL, NULL, _t('邮箱地址'), _t('请输入您注册时的邮箱地址')); |
||||||
|
// 添加class |
||||||
|
$mail->input->setAttribute('class', 'text-l w-100'); |
||||||
|
// 添加规则 |
||||||
|
$mail->addRule('required', _t('必须输入您的邮箱地址')); |
||||||
|
$mail->addRule('email', _t('请输入正确的邮箱格式')); |
||||||
|
$form->addInput($mail); |
||||||
|
// 动作 |
||||||
|
$do = new Typecho_Widget_Helper_Form_Element_Hidden('do', NULL, 'forget'); |
||||||
|
$form->addItem($do); |
||||||
|
// 提交按钮 |
||||||
|
$submit = new Typecho_Widget_Helper_Form_Element_Submit('submit', NULL, _t('提交')); |
||||||
|
// 添加class |
||||||
|
$submit->input->setAttribute('class', 'btn btn-l w-100 primary'); |
||||||
|
$form->addItem($submit); |
||||||
|
|
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重置密码表单 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param int $uid 用户编号 |
||||||
|
* |
||||||
|
* @return Typecho_Widget_Helper_Form |
||||||
|
*/ |
||||||
|
private function resetForm($uid = 0) |
||||||
|
{ |
||||||
|
// 创建表单 |
||||||
|
$form = new Typecho_Widget_Helper_Form($this->security->getIndex('action/lovekkcomment'), Typecho_Widget_Helper_Form::POST_METHOD); |
||||||
|
// 登录密码 |
||||||
|
$password = new Typecho_Widget_Helper_Form_Element_Password('password', NULL, NULL, _t('用户密码'), _t('建议使用特殊字符与字母、数字的混编样式,以增加系统安全性.')); |
||||||
|
// 设置class |
||||||
|
$password->input->setAttribute('class', 'text-l w-100'); |
||||||
|
// 添加规则 |
||||||
|
$password->addRule('required', _t('必须输入您的邮箱地址')); |
||||||
|
$password->addRule('minLength', _t('为了保证账户安全, 请设置最少8位数的密码'), 8); |
||||||
|
$form->addInput($password); |
||||||
|
// 密码确认 |
||||||
|
$confirm = new Typecho_Widget_Helper_Form_Element_Password('confirm', NULL, NULL, _t('用户密码确认'), _t('请确认您的密码, 与上面输入的密码保持一致.')); |
||||||
|
// 设置class |
||||||
|
$confirm->input->setAttribute('class', 'text-l w-100'); |
||||||
|
// 添加规则 |
||||||
|
$confirm->addRule('confirm', _t('您两次输入的密码不一致, 请重新输入'), 'password'); |
||||||
|
$form->addInput($confirm); |
||||||
|
// 动作 |
||||||
|
$do = new Typecho_Widget_Helper_Form_Element_Hidden('do', NULL, 'reset'); |
||||||
|
$form->addItem($do); |
||||||
|
// uid |
||||||
|
$uid = new Typecho_Widget_Helper_Form_Element_Hidden('uid', NULL, $uid); |
||||||
|
$form->addItem($uid); |
||||||
|
// 提交按钮 |
||||||
|
$submit = new Typecho_Widget_Helper_Form_Element_Submit('submit', NULL, _t('提交')); |
||||||
|
// 添加class |
||||||
|
$submit->input->setAttribute('class', 'btn btn-l w-100 primary'); |
||||||
|
$form->addItem($submit); |
||||||
|
|
||||||
|
return $form; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 找回密码提交 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* @throws Typecho_Exception |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
private function doForget() |
||||||
|
{ |
||||||
|
// 验证表单 |
||||||
|
if ( $error = $this->forgetForm()->validate() ) { |
||||||
|
// 显示错误信息 |
||||||
|
$this->widget('Widget_Notice')->set($error, 'error'); |
||||||
|
// 返回上一页 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 查询用户数据 |
||||||
|
$user = $this->db->fetchRow($this->select()->where('mail = ?', $this->request->mail)); |
||||||
|
// 没有用户 |
||||||
|
if ( !$user ) { |
||||||
|
// 输出错误 |
||||||
|
$this->widget('Widget_Notice')->set(_t('邮箱地址错误, 请核对后重新输入'), 'error'); |
||||||
|
// 返回上一页 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 过期时间 |
||||||
|
$expire = $this->_plugin->public_expire ? $this->_plugin->public_expire : 10; |
||||||
|
// 转换为秒数 |
||||||
|
$time = time() + $expire * 60; |
||||||
|
// 构造参数 |
||||||
|
$query = array( |
||||||
|
'reset' => 'true', |
||||||
|
't' => md5($user['uid'] . $user['name'] . $user['mail'] . $time), |
||||||
|
'm' => $user['mail'], |
||||||
|
'e' => $time |
||||||
|
); |
||||||
|
// 生成链接地址 |
||||||
|
$uri = Typecho_Common::url('/action/lovekkcomment?' . http_build_query($query), $this->options->index); |
||||||
|
// 请求参数 |
||||||
|
$data = array( |
||||||
|
'fromName' => ( !isset($this->_plugin->public_name) || is_null($this->_plugin->public_name) || empty($this->_plugin->public_name) ) ? trim($this->options->title) : $this->_plugin->public_name, // 发件人名称 |
||||||
|
'from' => $this->_plugin->public_mail, // 发件地址 |
||||||
|
'to' => $user['mail'], // 收件地址 |
||||||
|
'replyTo' => $this->_plugin->public_replyto // 回信地址 |
||||||
|
); |
||||||
|
// 标题 |
||||||
|
$data['subject'] = _t('您在 [' . trim($this->options->title) . '] 提交的密码找回申请!'); |
||||||
|
// 读取模板 |
||||||
|
$html = file_get_contents(dirname(__FILE__) . '/theme/forget.html'); |
||||||
|
// 替换内容 |
||||||
|
$data['html'] = str_replace( |
||||||
|
array( |
||||||
|
'{blogname}', |
||||||
|
'{blogurl}', |
||||||
|
'{mail}', |
||||||
|
'{sendtime}', |
||||||
|
'{resetlink}', |
||||||
|
'{expire}' |
||||||
|
), |
||||||
|
array( |
||||||
|
trim($this->options->title), |
||||||
|
trim($this->options->siteUrl), |
||||||
|
trim($user['mail']), |
||||||
|
trim(date('Y-m-d H:i:s', time())), |
||||||
|
trim($uri), |
||||||
|
trim($expire) |
||||||
|
), |
||||||
|
$html |
||||||
|
); |
||||||
|
// 根据接口选择 |
||||||
|
switch ( $this->_plugin->public_interface ) { |
||||||
|
case 'sendcloud': // Send Cloud |
||||||
|
// API User |
||||||
|
$data['apiUser'] = $this->_plugin->sendcloud_api_user; |
||||||
|
// API Key |
||||||
|
$data['apiKey'] = $this->_plugin->sendcloud_api_key; |
||||||
|
// 是否成功 |
||||||
|
if ( !LoveKKComment_Plugin::sendCloud($data) ) { |
||||||
|
// 输出错误信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('邮件发送失败, 请联系管理员解决!'), 'error'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 输出提示 |
||||||
|
$this->widget('Widget_Notice')->set(_t('已将重置密码信息发送至您的注册邮箱中, 请注意查收!'), 'success'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
case 'aliyun': // 阿里云 |
||||||
|
// 判断当前请求区域 |
||||||
|
switch ( $this->_plugin->ali_region ) { |
||||||
|
case 'hangzhou': // 杭州 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2015-11-23'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'cn-hangzhou'; |
||||||
|
break; |
||||||
|
case 'singapore': // 新加坡 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.ap-southeast-1.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2017-06-22'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'ap-southeast-1'; |
||||||
|
break; |
||||||
|
case 'sydney': // 悉尼 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.ap-southeast-2.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2017-06-22'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'ap-southeast-2'; |
||||||
|
break; |
||||||
|
} |
||||||
|
// AccessKeyId |
||||||
|
$data['accessid'] = $this->_plugin->ali_accesskey_id; |
||||||
|
// AccessKeySecret |
||||||
|
$data['accesssecret'] = $this->_plugin->ali_accesskey_secret; |
||||||
|
// 是否成功 |
||||||
|
if ( !LoveKKComment_Plugin::aliyun($data) ) { |
||||||
|
// 输出错误信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('邮件发送失败, 请联系管理员解决!'), 'error'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 输出提示 |
||||||
|
$this->widget('Widget_Notice')->set(_t('已将重置密码信息发送至您的注册邮箱中, 请注意查收!'), 'success'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
default: // SMTP |
||||||
|
// SMTP地址 |
||||||
|
$data['smtp_host'] = $this->_plugin->smtp_host; |
||||||
|
// SMTP端口 |
||||||
|
$data['smtp_port'] = $this->_plugin->smtp_port; |
||||||
|
// SMTP用户 |
||||||
|
$data['smtp_user'] = $this->_plugin->smtp_user; |
||||||
|
// SMTP密码 |
||||||
|
$data['smtp_pass'] = $this->_plugin->smtp_pass; |
||||||
|
// 验证模式 |
||||||
|
$data['smtp_auth'] = $this->_plugin->smtp_auth; |
||||||
|
// 加密模式 |
||||||
|
$data['smtp_secure'] = $this->_plugin->smtp_secure; |
||||||
|
// 是否成功 |
||||||
|
if ( !LoveKKComment_Plugin::smtp($data) ) { |
||||||
|
// 输出错误信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('邮件发送失败, 请联系管理员解决!'), 'error'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 输出提示 |
||||||
|
$this->widget('Widget_Notice')->set(_t('已将重置密码信息发送至您的注册邮箱中, 请注意查收!'), 'success'); |
||||||
|
// 跳转回去 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重置密码界面 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* @throws Typecho_Exception |
||||||
|
*/ |
||||||
|
private function reset() |
||||||
|
{ |
||||||
|
// 获取过期时间 |
||||||
|
$expire = $this->request->filter('int')->e; |
||||||
|
// 如果链接过期则输出错误 |
||||||
|
if ( time() > $expire ) { |
||||||
|
// 输出错误 |
||||||
|
$this->widget('Widget_Notice')->set(_t('抱歉, 您所提交的重置密码链接已过期, 请重新获取'), 'notice'); |
||||||
|
// 跳转到找回密码界面 |
||||||
|
$this->response->redirect(Typecho_Common::url('/action/lovekkcomment?forget', $this->options->index)); |
||||||
|
} |
||||||
|
// 查询用户数据 |
||||||
|
$user = $this->db->fetchRow($this->select()->where('mail = ?', $this->request->m)); |
||||||
|
// 没有用户 |
||||||
|
if ( !$user ) { |
||||||
|
// 输出错误 |
||||||
|
$this->widget('Widget_Notice')->set(_t('抱歉, 您的请求有误'), 'error'); |
||||||
|
// 返回登录界面 |
||||||
|
$this->resopnse->redirect($this->options->loginUrl); |
||||||
|
} |
||||||
|
// 取出数据 |
||||||
|
$token = $this->request->filter('strip_tags', 'trim', 'xss')->t; |
||||||
|
// 如果验证不通过 |
||||||
|
if ( $token != md5($user['uid'] . $user['name'] . $user['mail'] . $expire) ) { |
||||||
|
// 输出错误 |
||||||
|
$this->widget('Widget_Notice')->set(_t('抱歉, 您的请求验证错误'), 'error'); |
||||||
|
// 返回登录界面 |
||||||
|
$this->resopnse->redirect($this->options->loginUrl); |
||||||
|
} |
||||||
|
// 显示重置界面 |
||||||
|
$this->html('reset', $this->resetForm($user['uid'])); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重置密码提交 |
||||||
|
* |
||||||
|
* @access private |
||||||
|
* @throws Typecho_Exception |
||||||
|
*/ |
||||||
|
private function doReset() |
||||||
|
{ |
||||||
|
// 验证表单 |
||||||
|
if ( $error = $this->resetForm()->validate() ) { |
||||||
|
// 显示错误信息 |
||||||
|
$this->widget('Widget_Notice')->set($error, 'error'); |
||||||
|
// 返回上一页 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
// 获取用户uid |
||||||
|
$uid = $this->request->filter('integer')->uid; |
||||||
|
// 验证uid |
||||||
|
if ( !$uid ) { |
||||||
|
// 显示错误信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('抱歉, 您的请求验证失败'), 'error'); |
||||||
|
// 返回上一页 |
||||||
|
$this->response->goBack(); |
||||||
|
} |
||||||
|
echo '2'; |
||||||
|
// 初始化passwordhash |
||||||
|
$hasher = new PasswordHash(8, TRUE); |
||||||
|
// 密码加密 |
||||||
|
$password = $hasher->HashPassword($this->request->password); |
||||||
|
// 更新密码 |
||||||
|
if ( $this->update(array('password' => $password), $this->db->sql()->where('uid = ?', $uid)) ) { |
||||||
|
// 显示成功信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('密码重置成功'), 'success'); |
||||||
|
// 跳转登录页面 |
||||||
|
$this->response->redirect($this->options->loginUrl); |
||||||
|
} |
||||||
|
echo '3'; |
||||||
|
// 显示错误信息 |
||||||
|
$this->widget('Widget_Notice')->set(_t('密码重置失败, 请联系管理员'), 'error'); |
||||||
|
// 跳转登录页面 |
||||||
|
$this->response->redirect($this->options->loginUrl); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 操作方法 |
||||||
|
* |
||||||
|
* @access public |
||||||
|
* @throws Typecho_Exception |
||||||
|
*/ |
||||||
|
public function action() |
||||||
|
{ |
||||||
|
// 如果用户是登录状态则直接跳转至个人信息界面 |
||||||
|
if ( $this->user->hasLogin() ) $this->response->redirect($this->options->profileUrl); |
||||||
|
// 动作必须是POST提交 |
||||||
|
if ( $this->request->isPost() ) { |
||||||
|
// 忘记密码请求 |
||||||
|
$this->on($this->request->is('do=forget'))->doForget(); |
||||||
|
// 重置密码请求 |
||||||
|
$this->on($this->request->is('do=reset'))->doReset(); |
||||||
|
} |
||||||
|
// 忘记密码界面 |
||||||
|
if ( $this->request->is('forget') ) $this->html('forget', $this->forgetForm()); |
||||||
|
// 重置密码界面 |
||||||
|
if ( $this->request->is('reset') ) $this->reset(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2018 康康 |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all |
||||||
|
copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
SOFTWARE. |
@ -0,0 +1,927 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* Typecho 评论通知、找回密码插件 |
||||||
|
* |
||||||
|
* @package LoveKKComment |
||||||
|
* @author 康粑粑 |
||||||
|
* @version 1.0.5 |
||||||
|
* @link https://www.usebsd.com |
||||||
|
*/ |
||||||
|
|
||||||
|
if ( !defined('__TYPECHO_ROOT_DIR__') ) exit; |
||||||
|
// 时间区域 |
||||||
|
date_default_timezone_set('Asia/Shanghai'); |
||||||
|
|
||||||
|
class LoveKKComment_Plugin implements Typecho_Plugin_Interface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* 激活插件 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
*/ |
||||||
|
static public function activate() |
||||||
|
{ |
||||||
|
// 检查CURL |
||||||
|
if ( !function_exists('curl_init') ) { |
||||||
|
throw new Typecho_Plugin_Exception(_t('对不起,使用本插件必须要支持CURL')); |
||||||
|
} |
||||||
|
|
||||||
|
// 评论通知添加绑定 |
||||||
|
Typecho_Plugin::factory('Widget_Feedback')->finishComment = array(__CLASS__, 'doComment'); |
||||||
|
Typecho_Plugin::factory('Widget_Comments_Edit')->finishComment = array(__CLASS__, 'doComment'); |
||||||
|
Typecho_Plugin::factory('Widget_Comments_Edit')->mark = array(__CLASS__, 'doApproved'); |
||||||
|
// 检测当前版本 |
||||||
|
if ( version_compare(str_replace('/', '.', Typecho_Common::VERSION), '1.1.17.10.30') ) { |
||||||
|
// 注册异步回调 |
||||||
|
Typecho_Plugin::factory('Widget_Service')->sendMail = array(__CLASS__, 'sendMail'); |
||||||
|
Typecho_Plugin::factory('Widget_Service')->asyncApproved = array(__CLASS__, 'asyncApproved'); |
||||||
|
} |
||||||
|
|
||||||
|
// 找回密码绑定 |
||||||
|
Typecho_Plugin::factory('admin/footer.php')->end = array(__CLASS__, 'forgetLink'); |
||||||
|
// 找回密码动作添加 |
||||||
|
Helper::addAction('lovekkcomment', 'LoveKKComment_Action'); |
||||||
|
// 找回密码路由添加 |
||||||
|
Helper::addRoute('lovekkcomment_forget', '/lovekkcomment/forget', 'LoveKKComment_Action', 'forget'); |
||||||
|
Helper::addRoute('lovekkcomment_reset', '/lovekkcomment/reset', 'LoveKKCOmment_Action', 'reset'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 禁用插件 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
*/ |
||||||
|
static public function deactivate() |
||||||
|
{ |
||||||
|
// 删除动作 |
||||||
|
Helper::removeAction('lovekkcomment'); |
||||||
|
// 删除路由 |
||||||
|
Helper::removeRoute('lovekkcomment_forget'); |
||||||
|
Helper::removeRoute('lovekkcomment_reset'); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 插件配置 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param Typecho_Widget_Helper_Form $form |
||||||
|
*/ |
||||||
|
static public function config(Typecho_Widget_Helper_Form $form) |
||||||
|
{ |
||||||
|
// 公共区域 |
||||||
|
$public_section = new Typecho_Widget_Helper_Layout('div', array('class=' => 'typecho-page-title')); |
||||||
|
// 区块标题 |
||||||
|
$public_section->html('<h2>公共信息配置</h2>'); |
||||||
|
$form->addItem($public_section); |
||||||
|
// 找回密码开启 |
||||||
|
$public_forget = new Typecho_Widget_Helper_Form_Element_Checkbox('public_forget', array('enable' => _t('启用找回密码')), array('enable'), _t('是否启用找回密码功能'), _t('启用后,将在登录界面出现找回密码链接,并发送邮件至账号邮箱找回密码')); |
||||||
|
$form->addInput($public_forget); |
||||||
|
// 找回密码过期时间 |
||||||
|
$public_expire = new Typecho_Widget_Helper_Form_Element_Text('public_expire', NULL, '10', _t('验证过期时间'), _t('当发起找回密码申请后,会有一封链接邮件,此处定义链接过期时间,单位为分钟')); |
||||||
|
$form->addInput($public_expire); |
||||||
|
// Debug模式 |
||||||
|
$public_debug = new Typecho_Widget_Helper_Form_Element_Checkbox('public_debug', array('enable' => _t('启用Debug')), array('enable'), _t('是否启用Debug模式'), _t('启用后将在插件目录生成debug.txt文件,可记录邮件发送详细错误')); |
||||||
|
$form->addInput($public_debug); |
||||||
|
// 参数验证 |
||||||
|
$public_verify = new Typecho_Widget_Helper_Form_Element_Checkbox('public_verify', array('enable' => _t('启用配置验证')), array('enable'), _t('是否启用参数配置验证'), _t('启用配置验证后,将会在提交配置时进行验证,检测配置是否正确,启用后可能导致配置保存速度缓慢,注意,若使用SSL连接465端口模式,可能导致验证失败,建议使用TLS连接587端口发送邮件')); |
||||||
|
$form->addInput($public_verify); |
||||||
|
// 接口选择 |
||||||
|
$public_interface = new Typecho_Widget_Helper_Form_Element_Radio('public_interface', array('smtp' => _t('SMTP'), 'sendcloud' => _t('Send Cloud'), 'aliyun' => _t('阿里云推送')), NULL, _t('发信接口')); |
||||||
|
// 添加验证器并加入表单 |
||||||
|
$form->addInput($public_interface->addRule('required', _t('请选择发件接口'))); |
||||||
|
// 发件人名称 |
||||||
|
$public_name = new Typecho_Widget_Helper_Form_Element_Text('public_name', NULL, NULL, _t('发件人名称'), _t('邮件中显示的发信人名称,留空为博客名称')); |
||||||
|
$form->addInput($public_name); |
||||||
|
// 发件邮箱 |
||||||
|
$public_mail = new Typecho_Widget_Helper_Form_Element_Text('public_mail', NULL, NULL, _t('发件邮箱地址'), _t('邮件中显示的发信地址')); |
||||||
|
$form->addInput($public_mail->addRule('required', _t('请输入发件邮箱地址'))->addRule('email', _t('请输入正确的邮箱地址'))); |
||||||
|
// 回信地址 |
||||||
|
$public_replyto = new Typecho_Widget_Helper_Form_Element_Text('public_replyto', NULL, NULL, _t('邮件回复地址'), _t('附带在邮件中的默认回信地址')); |
||||||
|
$form->addInput($public_replyto->addRule('required', _t('请输入回信邮箱地址'))->addRule('email', _t('请输入正确的邮箱地址'))); |
||||||
|
|
||||||
|
// SMTP区块 |
||||||
|
$smtp_section = new Typecho_Widget_Helper_Layout('div', array('class=' => 'typecho-page-title')); |
||||||
|
$smtp_section->html('<h2>SMTP邮件发送设置</h2>'); |
||||||
|
$form->addItem($smtp_section); |
||||||
|
// SMTP地址 |
||||||
|
$smtp_host = new Typecho_Widget_Helper_Form_Element_Text('smtp_host', NULL, NULL, _t('SMTP地址'), _t('SMTP服务器连接地址')); |
||||||
|
$form->addInput($smtp_host); |
||||||
|
// SMTP端口 |
||||||
|
$smtp_port = new Typecho_Widget_Helper_Form_Element_Text('smtp_port', NULL, NULL, _t('SMTP端口'), _t('SMTP服务器连接端口')); |
||||||
|
$form->addInput($smtp_port); |
||||||
|
// SMTP用户名 |
||||||
|
$smtp_user = new Typecho_Widget_Helper_Form_Element_Text('smtp_user', NULL, NULL, _t('SMTP登录用户'), _t('SMTP登录用户名,一般为邮箱地址')); |
||||||
|
$form->addInput($smtp_user); |
||||||
|
// SMTP密码 |
||||||
|
$smtp_pass = new Typecho_Widget_Helper_Form_Element_Text('smtp_pass', NULL, NULL, _t('SMTP登录密码'), _t('一般为邮箱密码,但某些服务商需要生成特定密码')); |
||||||
|
$form->addInput($smtp_pass); |
||||||
|
// 是否需要验证 |
||||||
|
$smtp_auth = new Typecho_Widget_Helper_Form_Element_Checkbox('smtp_auth', array('enable' => _t('服务器需要验证')), array('enable'), _t('SMTP验证模式')); |
||||||
|
$form->addInput($smtp_auth); |
||||||
|
// 服务器安全模式 |
||||||
|
$smtp_secure = new Typecho_Widget_Helper_Form_Element_Radio('smtp_secure', array('none' => _t('无安全加密'), 'ssl' => _t('SSL加密'), 'tls' => _t('TLS加密')), 'none', _t('SMTP加密模式')); |
||||||
|
$form->addInput($smtp_secure); |
||||||
|
|
||||||
|
// SendCloud区块 |
||||||
|
$sendcloud_section = new Typecho_Widget_Helper_Layout('div', array('class=' => 'typecho-page-title')); |
||||||
|
// 区块标题 |
||||||
|
$sendcloud_section->html('<h2>Send Cloud邮件发送设置</h2>'); |
||||||
|
$form->addItem($sendcloud_section); |
||||||
|
// API USER |
||||||
|
$sendcloud_api_user = new Typecho_Widget_Helper_Form_Element_Text('sendcloud_api_user', NULL, NULL, _t('API USER'), _t('请填入在SendCloud生成的API_USER')); |
||||||
|
$form->addInput($sendcloud_api_user); |
||||||
|
// API KEY |
||||||
|
$sendcloud_api_key = new Typecho_Widget_Helper_Form_Element_Text('sendcloud_api_key', NULL, NULL, _t('API KEY'), _t('请填入在SendCloud生成的API_KEY')); |
||||||
|
$form->addInput($sendcloud_api_key); |
||||||
|
|
||||||
|
// 阿里云推送区块 |
||||||
|
$ali_section = new Typecho_Widget_Helper_Layout('div', array('class=' => 'typecho-page-title')); |
||||||
|
// 区块标题 |
||||||
|
$ali_section->html('<h2>阿里云推送邮件发送设置</h2>'); |
||||||
|
$form->addItem($ali_section); |
||||||
|
// 地域选择 |
||||||
|
$ali_region = new Typecho_Widget_Helper_Form_Element_Select('ali_region', array('hangzhou' => _t('华东1(杭州)'), 'singapore' => _t('亚太东南1(新加坡)'), 'sydney' => _t('亚太东南2(悉尼)')), NULL, _t('DM接入区域'), _t('请选择您的邮件推送所在服务器区域,请务必选择正确')); |
||||||
|
$form->addInput($ali_region); |
||||||
|
// AccessKey ID |
||||||
|
$ali_accesskey_id = new Typecho_Widget_Helper_Form_Element_Text('ali_accesskey_id', NULL, NULL, _t('AccessKey ID'), _t('请填入在阿里云生成的AccessKey ID')); |
||||||
|
$form->addInput($ali_accesskey_id); |
||||||
|
// Access Key Secret |
||||||
|
$ali_accesskey_secret = new Typecho_Widget_Helper_Form_Element_Text('ali_accesskey_secret', NULL, NULL, _t('Access Key Secret'), _t('请填入在阿里云生成的Access Key Secret')); |
||||||
|
$form->addInput($ali_accesskey_secret); |
||||||
|
} |
||||||
|
|
||||||
|
static public function personalConfig(Typecho_Widget_Helper_Form $form) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 检查配置信息 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param array $settings 配置数据 |
||||||
|
* |
||||||
|
* @return string |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
*/ |
||||||
|
static public function configCheck(array $settings) |
||||||
|
{ |
||||||
|
// 获取系统配置 |
||||||
|
$options = Helper::options(); |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = $options->plugin('LoveKKComment'); |
||||||
|
// 是否启用配置验证 |
||||||
|
if ( in_array('enable', $plugin->public_verify) ) { |
||||||
|
// 根据不同的接口选择来进行验证 |
||||||
|
switch ( $settings['public_interface'] ) { |
||||||
|
case 'sendcloud': // Send Cloud验证 |
||||||
|
if ( !isset($settings['sendcloud_api_user']) || empty($settings['sendcloud_api_user']) || !isset($settings['sendcloud_api_key']) || empty($settings['sendcloud_api_key']) ) { |
||||||
|
return _t('Send Cloud API USER与API KEY必须填写'); |
||||||
|
} |
||||||
|
$url = 'http://api.sendcloud.net/apiv2/apiuser/list?apiUser=' . $settings['sendcloud_api_user'] . '&apiKey=' . $settings['sendcloud_api_key']; |
||||||
|
// 使用curl连接send cloud并使用API_USER验证 |
||||||
|
$ch = curl_init(); |
||||||
|
curl_setopt($ch, CURLOPT_URL, $url); |
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
||||||
|
$result = curl_exec($ch); |
||||||
|
curl_close($ch); |
||||||
|
$result = json_decode($result); |
||||||
|
if ( 200 != $result->statusCode ) { |
||||||
|
return _t($result->message); |
||||||
|
} |
||||||
|
break; |
||||||
|
case 'aliyun': |
||||||
|
if ( !isset($settings['ali_region']) || empty($settings['ali_region']) || !isset($settings['ali_accesskey_id']) || empty($settings['ali_accesskey_id']) || !isset($settings['ali_accesskey_secret']) || empty($settings['ali_accesskey_secret']) ) { |
||||||
|
return _t('阿里云接入区域、AccessKey ID、Access Key Secret必须填写'); |
||||||
|
} |
||||||
|
break; |
||||||
|
default: // SMTP验证 |
||||||
|
// SMTP地址 |
||||||
|
if ( !isset($settings['smtp_host']) || empty($settings['smtp_host']) ) { |
||||||
|
return _t('SMTP地址必须填写'); |
||||||
|
} |
||||||
|
// SMTP端口 |
||||||
|
if ( !isset($settings['smtp_port']) || empty($settings['smtp_port']) ) { |
||||||
|
return _t('SMTP端口必须填写'); |
||||||
|
} |
||||||
|
// 载入SMTP |
||||||
|
if ( !class_exists('PHPMailer\PHPMailer\SMTP') ) { |
||||||
|
require dirname(__FILE__) . '/lib/SMTP.php'; |
||||||
|
} |
||||||
|
// 初始化SMTP类 |
||||||
|
$smtp = new \PHPMailer\PHPMailer\SMTP; |
||||||
|
// hostname |
||||||
|
$hostname = 'localhost.localdomain'; |
||||||
|
// 使用$_SERVER |
||||||
|
if ( isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME']) ) { |
||||||
|
$hostname = $_SERVER['SERVER_NAME']; |
||||||
|
} else if ( function_exists('gethostname') && gethostname() !== FALSE ) { // 使用gethostname |
||||||
|
$hostname = gethostname(); |
||||||
|
} else if ( php_uname('n') !== FALSE ) { // 使用php_uname |
||||||
|
$hostname = php_uname('n'); |
||||||
|
} |
||||||
|
// 连接 |
||||||
|
if ( !$smtp->connect($settings['smtp_host'], $settings['smtp_port'], 5) ) { |
||||||
|
return _t('SMTP连接失败,请检查SMTP地址及端口'); |
||||||
|
} |
||||||
|
// 发送hello |
||||||
|
if ( !$smtp->hello($hostname) ) { |
||||||
|
return _t('SMTP发送EHLO指令失败,错误信息:' . $smtp->getError()['error'] . ',若您使用的SMTP端口是465,加密方式为SSL,可能导致此错误,建议更换为TLS加密587端口后重试'); |
||||||
|
} |
||||||
|
// 获取服务器信息 |
||||||
|
$e = $smtp->getServerExtList(); |
||||||
|
// 是否需要StartTls |
||||||
|
if ( is_array($e) && array_key_exists('STARTTLS', $e) ) { |
||||||
|
// 验证模式是否为tls |
||||||
|
if ( 'tls' != $settings['smtp_secure'] ) { |
||||||
|
return _t('SMTP服务器要求tls加密'); |
||||||
|
} |
||||||
|
// starttls加密 |
||||||
|
$tls = $smtp->startTLS(); |
||||||
|
// 失败 |
||||||
|
if ( !$tls ) { |
||||||
|
return _t('tls加密失败,错误信息:' . $smtp->getError()['error']); |
||||||
|
} |
||||||
|
// 发送hello |
||||||
|
if ( !$smtp->hello($hostname) ) { |
||||||
|
return _t('SMTP发送EHLO指令失败,错误信息:' . $smtp->getError()['error'] . ',若您使用的SMTP端口是465,加密方式为SSL,可能导致此错误,建议更换为TLS加密587端口后重试'); |
||||||
|
} |
||||||
|
// 获取服务器信息 |
||||||
|
$e = $smtp->getServerExtList(); |
||||||
|
} |
||||||
|
|
||||||
|
// 登录验证 |
||||||
|
if ( is_array($e) && array_key_exists('AUTH', $e) || in_array('enable', $settings['smtp_auth']) ) { |
||||||
|
// 用户、密码 |
||||||
|
if ( !isset($settings['smtp_user']) || !isset($settings['smtp_pass']) || empty($settings['smtp_user']) || empty($settings['smtp_pass']) ) { |
||||||
|
return _t('SMTP登录账号及密码不能为空'); |
||||||
|
} |
||||||
|
// 没有启用验证 |
||||||
|
if ( !in_array('enable', $settings['smtp_auth']) ) { |
||||||
|
return _t('SMTP服务器要求身份验证'); |
||||||
|
} |
||||||
|
// 验证账号 |
||||||
|
if ( !$smtp->authenticate($settings['smtp_user'], $settings['smtp_pass']) ) { |
||||||
|
return _t('SMTP登录失败,错误信息:' . $smtp->getError()['error']); |
||||||
|
} |
||||||
|
} |
||||||
|
// 退出登录 |
||||||
|
$smtp->quit(TRUE); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 评论通知 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param mixed $comment 评论对象 |
||||||
|
* |
||||||
|
* @throws Typecho_Db_Exception |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
static public function doComment($comment) |
||||||
|
{ |
||||||
|
// 检测当前版本是否大于1.1/17.10.30 |
||||||
|
if ( version_compare(str_replace('/', '.', Typecho_Common::VERSION), '1.1.17.10.30') ) { |
||||||
|
// 调用异步回调模式 |
||||||
|
Helper::requestService('sendMail', $comment->coid); |
||||||
|
} else { |
||||||
|
self::sendMail($comment->coid); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 评论审核 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param mixed $comment 评论对象 |
||||||
|
* @param mixed $edit 编辑对象 |
||||||
|
* @param string $status 评论状态 |
||||||
|
* |
||||||
|
* @throws Typecho_Db_Exception |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
static public function doApproved($comment, $edit, $status) |
||||||
|
{ |
||||||
|
// 仅审核通过才发送邮件 |
||||||
|
if ( 'approved' == $status ) { |
||||||
|
// 检测当前版本是否大于1.1/17.10.30 |
||||||
|
if ( version_compare(str_replace('/', '.', Typecho_Common::VERSION), '1.1.17.10.30') ) { |
||||||
|
// 调用异步回调模式 |
||||||
|
Helper::requestService('asyncApproved', $comment); |
||||||
|
} else { |
||||||
|
self::sendMail($comment->coid, TRUE); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 异步审核回调 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param mixed $comment 评论对象 |
||||||
|
* |
||||||
|
* @throws Typecho_Db_Exception |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
static public function asyncApproved($comment) |
||||||
|
{ |
||||||
|
// 调用异步邮件发送 |
||||||
|
self::sendMail($comment->coid, TRUE); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 邮件发送操作 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param int $commentId 评论编号 |
||||||
|
* @param bool $isApproved 是否为审核操作 |
||||||
|
* |
||||||
|
* @return bool|string |
||||||
|
* @throws Typecho_Db_Exception |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
static public function sendMail($commentId, $isApproved = FALSE) |
||||||
|
{ |
||||||
|
// 重新获取评论数据 |
||||||
|
$comment = self::getWidget('Comments', 'coid', $commentId); |
||||||
|
// 收件人地址 |
||||||
|
$address = $comment->mail; |
||||||
|
// 上级评论对象 |
||||||
|
$parentComment = NULL; |
||||||
|
// 不是帖子发表者 |
||||||
|
if ( $comment->authorId != $comment->ownerId ) { |
||||||
|
// 获取作者信息 |
||||||
|
$author = self::getWidget('Users', 'uid', $comment->ownerId); |
||||||
|
// 收件地址 |
||||||
|
$address = $author->mail; |
||||||
|
// 上级评论 |
||||||
|
$parentComment = NULL; |
||||||
|
} |
||||||
|
|
||||||
|
// 评论回复 |
||||||
|
if ( 0 < $comment->parent ) { |
||||||
|
// 获取上级对象 |
||||||
|
$parentComment = self::getWidget('Comments', 'coid', $comment->parent); |
||||||
|
// 是否获取到且用户ID不同或邮件地址不同 |
||||||
|
if ( isset($parentComment->coid) && $comment->mail != $parentComment->mail ) { |
||||||
|
// 收件地址 |
||||||
|
$address = $parentComment->mail; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// 获取系统配置 |
||||||
|
$options = Helper::options(); |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = $options->plugin('LoveKKComment'); |
||||||
|
// 请求参数 |
||||||
|
$data = array( |
||||||
|
'fromName' => ( !isset($plugin->public_name) || empty($plugin->public_name) ) ? trim($options->title) : $plugin->public_name, // 发件人名称 |
||||||
|
'from' => $plugin->public_mail, // 发件地址 |
||||||
|
'to' => $address, // 收件地址 |
||||||
|
'replyTo' => $plugin->public_replyto // 回信地址 |
||||||
|
); |
||||||
|
|
||||||
|
// 如果是通过审核 |
||||||
|
if ( $isApproved ) { |
||||||
|
// 邮件标题 |
||||||
|
$data['subject'] = _t('您在 [' . trim($options->title) . '] 发表的评论已通过审核!'); |
||||||
|
// 读取模板 |
||||||
|
$html = file_get_contents(dirname(__FILE__) . '/theme/approved.html'); |
||||||
|
// 替换内容 |
||||||
|
$data['html'] = str_replace( |
||||||
|
array( |
||||||
|
'{blogUrl}', // 博客地址 |
||||||
|
'{blogName}', // 博客名称 |
||||||
|
'{author}', // 作者名称 |
||||||
|
'{permalink}', // 文章链接 |
||||||
|
'{title}', // 文章标题 |
||||||
|
'{text}' // 评论内容 |
||||||
|
), |
||||||
|
array( |
||||||
|
trim($options->siteUrl), |
||||||
|
trim($options->title), |
||||||
|
trim($comment->author), |
||||||
|
trim($comment->permalink), |
||||||
|
trim($comment->title), |
||||||
|
trim($comment->text) |
||||||
|
), |
||||||
|
$html |
||||||
|
); |
||||||
|
} else { |
||||||
|
// 有上级评论 |
||||||
|
if ( !is_null($parentComment) ) { |
||||||
|
// 标题 |
||||||
|
$data['subject'] = _t('您在 [' . trim($options->title) . '] 的评论有了新的回复!'); |
||||||
|
// 读取模板 |
||||||
|
$html = file_get_contents(dirname(__FILE__) . '/theme/reply.html'); |
||||||
|
// 获取文章 |
||||||
|
$post = self::getWidget('Contents', 'cid', $parentComment->cid); |
||||||
|
// 替换模板 |
||||||
|
$data['html'] = str_replace( |
||||||
|
array( |
||||||
|
'{blogUrl}', // 博客地址 |
||||||
|
'{blogName}', // 博客名称 |
||||||
|
'{author}', // 作者名称 |
||||||
|
'{permalink}', // 文章链接 |
||||||
|
'{title}', // 文章标题 |
||||||
|
'{text}', // 评论内容 |
||||||
|
'{replyAuthor}', // 回复者名称 |
||||||
|
'{replyText}', // 回复内容 |
||||||
|
'{commentUrl}' // 评论地址 |
||||||
|
), array( |
||||||
|
trim($options->siteUrl), |
||||||
|
trim($options->title), |
||||||
|
trim($parentComment->author), |
||||||
|
trim($post->permalink), |
||||||
|
trim($post->title), |
||||||
|
trim($parentComment->text), |
||||||
|
trim($comment->author), |
||||||
|
trim($comment->text), |
||||||
|
trim($comment->permalink) |
||||||
|
), $html |
||||||
|
); |
||||||
|
} else { |
||||||
|
// 标题 |
||||||
|
$data['subject'] = _t('您在 [' . trim($options->title) . '] 发表的文章有新评论!'); |
||||||
|
// 读取模板 |
||||||
|
$html = file_get_contents(dirname(__FILE__) . '/theme/author.html'); |
||||||
|
// 替换模板内容 |
||||||
|
$data['html'] = str_replace( |
||||||
|
array( |
||||||
|
'{blogUrl}', // 博客地址 |
||||||
|
'{blogName}', // 博客名称 |
||||||
|
'{author}', // 作者名称 |
||||||
|
'{permalink}', // 文章地址 |
||||||
|
'{title}', // 文章标题 |
||||||
|
'{text}' // 评论内容 |
||||||
|
), array( |
||||||
|
trim($options->siteUrl), |
||||||
|
trim($options->title), |
||||||
|
trim($comment->author), |
||||||
|
trim($comment->permalink), |
||||||
|
trim($comment->title), |
||||||
|
trim($comment->text) |
||||||
|
), $html |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
// 根据接口进行操作 |
||||||
|
switch ( $plugin->public_interface ) { |
||||||
|
case 'sendcloud': // Send Cloud |
||||||
|
// API User |
||||||
|
$data['apiUser'] = $plugin->sendcloud_api_user; |
||||||
|
// API Key |
||||||
|
$data['apiKey'] = $plugin->sendcloud_api_key; |
||||||
|
return self::sendCloud($data); |
||||||
|
case 'aliyun': // 阿里云推送 |
||||||
|
// 判断当前请求区域 |
||||||
|
switch ( $plugin->ali_region ) { |
||||||
|
case 'hangzhou': // 杭州 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2015-11-23'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'cn-hangzhou'; |
||||||
|
break; |
||||||
|
case 'singapore': // 新加坡 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.ap-southeast-1.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2017-06-22'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'ap-southeast-1'; |
||||||
|
break; |
||||||
|
case 'sydney': // 悉尼 |
||||||
|
// API地址 |
||||||
|
$data['api'] = 'https://dm.ap-southeast-2.aliyuncs.com/'; |
||||||
|
// API版本号 |
||||||
|
$data['version'] = '2017-06-22'; |
||||||
|
// 机房信息 |
||||||
|
$data['region'] = 'ap-southeast-2'; |
||||||
|
break; |
||||||
|
} |
||||||
|
// AccessKeyId |
||||||
|
$data['accessid'] = $plugin->ali_accesskey_id; |
||||||
|
// AccessKeySecret |
||||||
|
$data['accesssecret'] = $plugin->ali_accesskey_secret; |
||||||
|
return self::aliyun($data); |
||||||
|
default: // SMTP |
||||||
|
// SMTP地址 |
||||||
|
$data['smtp_host'] = $plugin->smtp_host; |
||||||
|
// SMTP端口 |
||||||
|
$data['smtp_port'] = $plugin->smtp_port; |
||||||
|
// SMTP用户 |
||||||
|
$data['smtp_user'] = $plugin->smtp_user; |
||||||
|
// SMTP密码 |
||||||
|
$data['smtp_pass'] = $plugin->smtp_pass; |
||||||
|
// 验证模式 |
||||||
|
$data['smtp_auth'] = $plugin->smtp_auth; |
||||||
|
// 加密模式 |
||||||
|
$data['smtp_secure'] = $plugin->smtp_secure; |
||||||
|
return self::smtp($data); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Send Cloud 邮件发送 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param array $data 公共参数 |
||||||
|
* |
||||||
|
* @return bool|string |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
*/ |
||||||
|
static public function sendCloud($data) |
||||||
|
{ |
||||||
|
// 初始化Curl |
||||||
|
$ch = curl_init(); |
||||||
|
// 请求地址 |
||||||
|
curl_setopt($ch, CURLOPT_URL, 'http://api.sendcloud.net/apiv2/mail/send'); |
||||||
|
// 基础验证 |
||||||
|
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); |
||||||
|
// 返回数据 |
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
||||||
|
// POST请求 |
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); |
||||||
|
// 请求参数 |
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); |
||||||
|
// 执行请求 |
||||||
|
$result = curl_exec($ch); |
||||||
|
// 获取错误代码 |
||||||
|
$errno = curl_errno($ch); |
||||||
|
// 获取错误信息 |
||||||
|
$error = curl_error($ch); |
||||||
|
// 关闭请求 |
||||||
|
curl_close($ch); |
||||||
|
// 成功标识 |
||||||
|
$flag = TRUE; |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = Helper::options()->plugin('LoveKKComment'); |
||||||
|
// 如果开启了Debug |
||||||
|
if ( in_array('enable', $plugin->public_debug) ) { |
||||||
|
// 记录时间 |
||||||
|
$log = '[Send Cloud] ' . date('Y-m-d H:i:s') . ': ' . PHP_EOL; |
||||||
|
// 如果失败 |
||||||
|
if ( $errno ) { |
||||||
|
// 设置为失败 |
||||||
|
$flag = FALSE; |
||||||
|
$log .= _t('邮件发送失败, 错误代码:' . $errno . ',错误提示: ' . $error . PHP_EOL); |
||||||
|
} |
||||||
|
// 转换为json |
||||||
|
if ( $json = json_decode($result) ) { |
||||||
|
// 失败 |
||||||
|
if ( 200 != $json->statusCode ) { |
||||||
|
// 设置为失败 |
||||||
|
$flag = FALSE; |
||||||
|
$log .= _t('邮件发送失败,错误提示:' . $json->message . PHP_EOL); |
||||||
|
} |
||||||
|
} |
||||||
|
// 记录返回值 |
||||||
|
$log .= _t('邮件发送返回数据:' . serialize($result) . PHP_EOL); |
||||||
|
// 输出分隔 |
||||||
|
$log .= '-------------------------------------------' . PHP_EOL . PHP_EOL . PHP_EOL; |
||||||
|
// 写入文件 |
||||||
|
file_put_contents(__DIR__ . '/debug.txt', $log, FILE_APPEND); |
||||||
|
} |
||||||
|
// 返回结果 |
||||||
|
return $flag; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 阿里云邮件发送 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param array $param 公共参数 |
||||||
|
* |
||||||
|
* @return bool|string |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
*/ |
||||||
|
static public function aliyun($param) |
||||||
|
{ |
||||||
|
// 重新组合为阿里云所使用的参数 |
||||||
|
$data = array( |
||||||
|
'Action' => 'SingleSendMail', // 操作接口名 |
||||||
|
'AccountName' => $param['from'], // 发件地址 |
||||||
|
'ReplyToAddress' => "true", // 回信地址 |
||||||
|
'AddressType' => 1, // 地址类型 |
||||||
|
'ToAddress' => $param['to'], // 收件地址 |
||||||
|
'FromAlias' => $param['fromName'], // 发件人名称 |
||||||
|
'Subject' => $param['subject'], // 邮件标题 |
||||||
|
'HtmlBody' => $param['html'], // 邮件内容 |
||||||
|
'Format' => 'JSON', // 返回JSON |
||||||
|
'Version' => $param['version'], // API版本号 |
||||||
|
'AccessKeyId' => $param['accessid'], // Access Key ID |
||||||
|
'SignatureMethod' => 'HMAC-SHA1', // 签名方式 |
||||||
|
'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'), // 请求时间 |
||||||
|
'SignatureVersion' => '1.0', // 签名算法版本 |
||||||
|
'SignatureNonce' => md5(time()), // 唯一随机数 |
||||||
|
'RegionId' => $param['region'] // 机房信息 |
||||||
|
); |
||||||
|
// 请求签名 |
||||||
|
$data['Signature'] = self::sign($data, $param['accesssecret']); |
||||||
|
// 初始化Curl |
||||||
|
$ch = curl_init(); |
||||||
|
// 设置为POST请求 |
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); |
||||||
|
// 请求地址 |
||||||
|
curl_setopt($ch, CURLOPT_URL, $param['api']); |
||||||
|
// 返回数据 |
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); |
||||||
|
// 提交参数 |
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, self::getPostHttpBody($data)); |
||||||
|
// 关闭ssl验证 |
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); |
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); |
||||||
|
// 执行请求 |
||||||
|
$result = curl_exec($ch); |
||||||
|
// 获取错误代码 |
||||||
|
$errno = curl_errno($ch); |
||||||
|
// 获取错误信息 |
||||||
|
$error = curl_error($ch); |
||||||
|
// 获取返回状态码 |
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||||||
|
// 关闭请求 |
||||||
|
curl_close($ch); |
||||||
|
// 成功标识 |
||||||
|
$flag = TRUE; |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = Helper::options()->plugin('LoveKKComment'); |
||||||
|
// 如果开启了Debug |
||||||
|
if ( in_array('enable', $plugin->public_debug) ) { |
||||||
|
// 记录时间 |
||||||
|
$log = '[Aliyun] ' . date('Y-m-d H:i:s') . ': ' . PHP_EOL; |
||||||
|
// 如果失败 |
||||||
|
if ( $errno ) { |
||||||
|
// 设置失败 |
||||||
|
$flag = FALSE; |
||||||
|
$log .= _t('邮件发送失败, 错误代码:' . $errno . ',错误提示: ' . $error . PHP_EOL); |
||||||
|
} |
||||||
|
// 如果失败 |
||||||
|
if ( 400 <= $httpCode ) { |
||||||
|
// 设置失败 |
||||||
|
$flag = FALSE; |
||||||
|
// 尝试转换json |
||||||
|
if ( $json = json_decode($result) ) { |
||||||
|
$log .= _t('邮件发送失败,错误代码:' . $json->Code . ',错误提示:' . $json->Message . PHP_EOL); |
||||||
|
} else { |
||||||
|
$log .= _t('邮件发送失败, 请求返回HTTP Code:' . $httpCode . PHP_EOL); |
||||||
|
} |
||||||
|
} |
||||||
|
// 记录返回值 |
||||||
|
$log .= _t('邮件发送返回数据:' . serialize($result) . PHP_EOL); |
||||||
|
// 输出分隔 |
||||||
|
$log .= '-------------------------------------------' . PHP_EOL . PHP_EOL . PHP_EOL; |
||||||
|
// 写入文件 |
||||||
|
file_put_contents(__DIR__ . '/debug.txt', $log, FILE_APPEND); |
||||||
|
} |
||||||
|
// 返回结果 |
||||||
|
return $flag; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* SMTP邮件发送 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access public |
||||||
|
* |
||||||
|
* @param array $param 公共参数 |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
* @throws Typecho_Plugin_Exception |
||||||
|
* @throws \PHPMailer\PHPMailer\Exception |
||||||
|
*/ |
||||||
|
static public function smtp($param) |
||||||
|
{ |
||||||
|
// 载入PHPMailer |
||||||
|
if ( !class_exists('PHPMailer\PHPMailer\PHPMailer') ) { |
||||||
|
require dirname(__FILE__) . '/lib/PHPMailer.php'; |
||||||
|
} |
||||||
|
// 载入SMTP |
||||||
|
if ( !class_exists('PHPMailer\PHPMailer\SMTP') ) { |
||||||
|
require dirname(__FILE__) . '/lib/SMTP.php'; |
||||||
|
} |
||||||
|
// 载入Exception |
||||||
|
if ( !class_exists('PHPMaile\PHPMailer\Exception') ) { |
||||||
|
require dirname(__FILE__) . '/lib/Exception.php'; |
||||||
|
} |
||||||
|
|
||||||
|
// 初始化PHPMailer |
||||||
|
$mail = new PHPMailer\PHPMailer\PHPMailer(FALSE); |
||||||
|
// 设置编码 |
||||||
|
$mail->CharSet = 'UTF-8'; |
||||||
|
// 启用SMTP |
||||||
|
$mail->isSMTP(); |
||||||
|
// SMTP地址 |
||||||
|
$mail->Host = $param['smtp_host']; |
||||||
|
// SMTP端口 |
||||||
|
$mail->Port = $param['smtp_port'] ?: 25; |
||||||
|
// SMTP用户名 |
||||||
|
$mail->Username = $param['smtp_user']; |
||||||
|
// SMTP密码 |
||||||
|
$mail->Password = $param['smtp_pass']; |
||||||
|
// 是否需要验证 |
||||||
|
if ( in_array('enable', $param['smtp_auth']) ) { |
||||||
|
// 开启验证 |
||||||
|
$mail->SMTPAuth = TRUE; |
||||||
|
} |
||||||
|
// 加密模式 |
||||||
|
if ( 'none' != $param['smtp_secure'] ) { |
||||||
|
// 设置加密模式 |
||||||
|
$mail->SMTPSecure = $param['smtp_secure']; |
||||||
|
} |
||||||
|
// 发件人信息 |
||||||
|
$mail->setFrom($param['from'], $param['fromName']); |
||||||
|
// 回信信息 |
||||||
|
$mail->addReplyTo($param['replyTo'], $param['fromName']); |
||||||
|
// 收件地址 |
||||||
|
$mail->addAddress($param['to']); |
||||||
|
// HTML格式 |
||||||
|
$mail->isHTML(TRUE); |
||||||
|
// Debug级别 |
||||||
|
$mail->SMTPDebug = 4; |
||||||
|
// 邮件标题 |
||||||
|
$mail->Subject = $param['subject']; |
||||||
|
// 邮件内容 |
||||||
|
$mail->msgHTML($param['html']); |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = Helper::options()->plugin('LoveKKComment'); |
||||||
|
// 发送邮件 |
||||||
|
$result = $mail->send(); |
||||||
|
// 如果开启了Debug |
||||||
|
if ( in_array('enable', $plugin->public_debug) ) { |
||||||
|
// 记录时间 |
||||||
|
$log = '[SMTP] ' . date('Y-m-d H:i:s') . ': ' . PHP_EOL; |
||||||
|
$log .= 'data: ' . serialize($param) . PHP_EOL . PHP_EOL; |
||||||
|
// 记录返回值及PHPMailer错误 |
||||||
|
$log .= _t('邮件发送返回数据:' . serialize($result) . '; 错误信息: ' . $mail->ErrorInfo . PHP_EOL); |
||||||
|
// 输出分隔 |
||||||
|
$log .= '-------------------------------------------' . PHP_EOL . PHP_EOL . PHP_EOL; |
||||||
|
// 写入文件 |
||||||
|
file_put_contents(__DIR__ . '/debug.txt', $log, FILE_APPEND); |
||||||
|
} |
||||||
|
// 结果 |
||||||
|
return $result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 添加找回密码链接 |
||||||
|
*/ |
||||||
|
static public function forgetLink() |
||||||
|
{ |
||||||
|
// 获取系统配置选项 |
||||||
|
$options = Helper::options(); |
||||||
|
// 获取插件配置 |
||||||
|
$plugin = $options->plugin('LoveKKComment'); |
||||||
|
// 如果开启了密码找回 |
||||||
|
if ( in_array('enable', $plugin->public_forget) ) { |
||||||
|
// 初始化request对象 |
||||||
|
$request = Typecho_Request::getInstance(); |
||||||
|
// 获取当前请求 |
||||||
|
$pathinfo = $request->getRequestUrl(); |
||||||
|
// 如果是登录页面则添加忘记密码链接 |
||||||
|
if ( preg_match('/\/login\.php/i', $pathinfo) ) { |
||||||
|
?> |
||||||
|
<script> |
||||||
|
var forget = document.createElement('a'); |
||||||
|
forget.href = '<?php echo Typecho_Common::url('/action/lovekkcomment?forget', Helper::options()->index);?>';
|
||||||
|
var text = document.createTextNode('<?php _e('忘记密码');?>');
|
||||||
|
forget.appendChild(text); |
||||||
|
document.getElementsByClassName('more-link')[0].appendChild(forget); |
||||||
|
</script> |
||||||
|
<?php |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取Widget对象 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param string $table 数据表名 |
||||||
|
* @param string $key 查询关键字 |
||||||
|
* @param mixed $val 数据数据 |
||||||
|
* |
||||||
|
* @return mixed |
||||||
|
* @throws Typecho_Db_Exception |
||||||
|
*/ |
||||||
|
static private function getWidget($table, $key, $val) |
||||||
|
{ |
||||||
|
// 类名称 |
||||||
|
$className = 'Widget_Abstract_' . $table; |
||||||
|
// 初始化数据库 |
||||||
|
$db = Typecho_Db::get(); |
||||||
|
// 初始化类 |
||||||
|
$widget = new $className(Typecho_Request::getInstance(), Typecho_Widget_Helper_Empty::getInstance()); |
||||||
|
// 查询数据 |
||||||
|
$db->fetchRow($widget->select()->where($key . ' = ?', $val)->limit(1), array($widget, 'push')); |
||||||
|
|
||||||
|
return $widget; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 阿里云签名 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param array $param 签名参数 |
||||||
|
* @param string $accesssecret 秘钥 |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
static private function sign($param, $accesssecret) |
||||||
|
{ |
||||||
|
// 参数排序 |
||||||
|
ksort($param); |
||||||
|
// 组合基础 |
||||||
|
$stringToSign = 'POST&' . self::percentEncode('/') . '&'; |
||||||
|
// 临时变量 |
||||||
|
$tmp = ''; |
||||||
|
// 循环参数列表 |
||||||
|
foreach ( $param as $k => $v ) { |
||||||
|
// 组合参数 |
||||||
|
$tmp .= '&' . self::percentEncode($k) . '=' . self::percentEncode($v); |
||||||
|
} |
||||||
|
// 去除最后一个& |
||||||
|
$tmp = trim($tmp, '&'); |
||||||
|
// 组合签名参数 |
||||||
|
$stringToSign = $stringToSign . self::percentEncode($tmp); |
||||||
|
// 数据签名 |
||||||
|
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $accesssecret . '&', TRUE)); |
||||||
|
// 返回签名 |
||||||
|
return $signature; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 阿里云签名编码转换 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param string $val 要转换的编码 |
||||||
|
* |
||||||
|
* @return string|string[]|null |
||||||
|
*/ |
||||||
|
static private function percentEncode($val) |
||||||
|
{ |
||||||
|
// URL编码 |
||||||
|
$res = urlencode($val); |
||||||
|
// 加号转换为%20 |
||||||
|
$res = preg_replace('/\+/', '%20', $res); |
||||||
|
// 星号转换为%2A |
||||||
|
$res = preg_replace('/\*/', '%2A', $res); |
||||||
|
// %7E转换为~ |
||||||
|
$res = preg_replace('/%7E/', '~', $res); |
||||||
|
return $res; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 阿里云请求参数组合 |
||||||
|
* |
||||||
|
* @static |
||||||
|
* @access private |
||||||
|
* |
||||||
|
* @param array $param 发送参数 |
||||||
|
* |
||||||
|
* @return bool|string |
||||||
|
*/ |
||||||
|
static private function getPostHttpBody($param) |
||||||
|
{ |
||||||
|
// 空字符串 |
||||||
|
$str = ""; |
||||||
|
// 循环参数 |
||||||
|
foreach ( $param as $k => $v ) { |
||||||
|
// 组合参数 |
||||||
|
$str .= $k . '=' . urlencode($v) . '&'; |
||||||
|
} |
||||||
|
// 去除第一个& |
||||||
|
return substr($str, 0, -1); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,89 @@ |
|||||||
|
## 插件简介 |
||||||
|
|
||||||
|
LoveKKComment是一款Typecho邮件通知类插件,支持SMTP、Send Cloud、阿里云邮件推送三种邮件通知方式。 |
||||||
|
|
||||||
|
在评论审核通过、用户评论文章、用户评论被回复时对不同场景进行不同的邮件通知。 |
||||||
|
|
||||||
|
## 安装方法 |
||||||
|
|
||||||
|
> 1. 至[releases](https://github.com/typecho-fans/plugins/releases/tag/plugins-H_to_L)中下载最新版本插件; |
||||||
|
> 2. 将下载的压缩包进行解压并上传至`Typecho`插件目录中,注意目录名称更改为`LoveKKComment`; |
||||||
|
> 3. 后台激活插件; |
||||||
|
> 4. 根据自己的实际情况选择邮件发送接口方式; |
||||||
|
> 5. 根据所选的邮件发送接口,配置相应接口参数。 |
||||||
|
|
||||||
|
## 自定义模板说明 |
||||||
|
|
||||||
|
插件共有三个模板,保存在插件`theme`目录下,分别为: |
||||||
|
|
||||||
|
> 1. approved.html:邮件审核通过通知模板。 |
||||||
|
> 2. author.html:文章评论通知作者模板。 |
||||||
|
> 3. reply.html:评论回复通知被回复者模板。 |
||||||
|
|
||||||
|
三个模板使用变量作为内容替换,您只需在自己的模板中增加相应的模板变量即可,模板变量列表如下: |
||||||
|
|
||||||
|
### approved.html |
||||||
|
|
||||||
|
> 1. {blogUrl}:博客地址 |
||||||
|
> 2. {blogName}:博客名称 |
||||||
|
> 3. {author}:评论者名称 |
||||||
|
> 4. {permalink}:文章链接 |
||||||
|
> 5. {title}:文章标题 |
||||||
|
> 6. {text}:评论内容 |
||||||
|
|
||||||
|
### author.html |
||||||
|
|
||||||
|
author.html内变量与approved.html内变量一致。 |
||||||
|
|
||||||
|
### reply.html |
||||||
|
|
||||||
|
> 1. {blogUrl}:博客地址 |
||||||
|
> 2. {blogName}:博客名称 |
||||||
|
> 3. {author}:被回复者名称 |
||||||
|
> 4. {permalink}:文章链接 |
||||||
|
> 5. {title}:文章标题 |
||||||
|
> 6. {text}:被回复者评论内容 |
||||||
|
> 7. {replyAuthor}:回复者名称 |
||||||
|
> 8. {replyText}:回复内容 |
||||||
|
|
||||||
|
## 更新日志 |
||||||
|
|
||||||
|
### 2019.01.08 |
||||||
|
|
||||||
|
> 1. 新增异步回调邮件发送模式,仅在Typecho版本大于1.1/17.10.30时使用 |
||||||
|
> 2. 新增配置验证模式,Send Cloud验证API USER及API KEY正确性,SMTP验证登录正确性,阿里云仅验证是否填写 |
||||||
|
> 3. 与LoveKKForget插件合并,可自由开启 |
||||||
|
> 4. 去除新版本检测功能,请使用[TeStore](http://www.yzmb.me/archives/net/testore-for-typecho)进行版本检测 |
||||||
|
|
||||||
|
**修复** |
||||||
|
|
||||||
|
> Typecho的当前稳定版1.1和开发版1.2的Helper中,都有一个widgetById方法,是直接根据表名和主键获取数据对象,由于稳定版在初始化数据类时没有传入参数,导致初始化错误,引起程序报错,开发版已经修复了这个问题。 |
||||||
|
> 而今日更新的1.0.5插件,在编写时未注意,将原本自己编写的获取数据对象方法弃用,使用官方的widgetById方法,导致了在1.1正式版中评论报错问题,2019.01.08 23:53修复此问题,若存在此问题的朋友,请下载修复后的插件,覆盖`Plugin.php`文件即可。 |
||||||
|
|
||||||
|
### 2018.09.03 |
||||||
|
|
||||||
|
> 由于今年备案规则,限制部分后缀域名备案,担心后续会影响网站数据,将仓库再次迁移回github.com |
||||||
|
|
||||||
|
### 2018.08.19 |
||||||
|
|
||||||
|
> 1. 新增Debug模式 |
||||||
|
> 2. 修复PHPMailer发信时的小错误 |
||||||
|
|
||||||
|
### 2018.08.14 |
||||||
|
|
||||||
|
> 1. 增加SMTP邮件发送方式 |
||||||
|
> 2. 增加阿里云邮件推送发送方式 |
||||||
|
> 3. 更改SendCloud发送方式为普通发送,不再使用模板发送 |
||||||
|
> 4. 邮件模板更改为本地HTML模板 |
||||||
|
> 5. 自由选择邮件发送方式 |
||||||
|
> 6. 去除Action.php文件 |
||||||
|
|
||||||
|
### 2018.08.08 |
||||||
|
|
||||||
|
> 1. 修正版本检测地址 |
||||||
|
> 2. 符合TeStore插件 |
||||||
|
> 3. 仓库迁移 |
||||||
|
|
||||||
|
### 2018.03.28 |
||||||
|
|
||||||
|
> 增加评论作者通知功能(用户评论后自动发送邮件通知文章作者) |
@ -0,0 +1,39 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* PHPMailer Exception class. |
||||||
|
* PHP Version 5.5. |
||||||
|
* |
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project |
||||||
|
* |
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> |
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> |
||||||
|
* @author Brent R. Matzelle (original founder) |
||||||
|
* @copyright 2012 - 2017 Marcus Bointon |
||||||
|
* @copyright 2010 - 2012 Jim Jagielski |
||||||
|
* @copyright 2004 - 2009 Andy Prevost |
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License |
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT |
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer; |
||||||
|
|
||||||
|
/** |
||||||
|
* PHPMailer exception handler. |
||||||
|
* |
||||||
|
* @author Marcus Bointon <phpmailer@synchromedia.co.uk> |
||||||
|
*/ |
||||||
|
class Exception extends \Exception |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Prettify error message output. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function errorMessage() |
||||||
|
{ |
||||||
|
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* PHPMailer - PHP email creation and transport class. |
||||||
|
* PHP Version 5.5. |
||||||
|
* |
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project |
||||||
|
* |
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> |
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> |
||||||
|
* @author Brent R. Matzelle (original founder) |
||||||
|
* @copyright 2012 - 2015 Marcus Bointon |
||||||
|
* @copyright 2010 - 2012 Jim Jagielski |
||||||
|
* @copyright 2004 - 2009 Andy Prevost |
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License |
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT |
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer; |
||||||
|
|
||||||
|
use League\OAuth2\Client\Grant\RefreshToken; |
||||||
|
use League\OAuth2\Client\Provider\AbstractProvider; |
||||||
|
use League\OAuth2\Client\Token\AccessToken; |
||||||
|
|
||||||
|
/** |
||||||
|
* OAuth - OAuth2 authentication wrapper class. |
||||||
|
* Uses the oauth2-client package from the League of Extraordinary Packages. |
||||||
|
* |
||||||
|
* @see http://oauth2-client.thephpleague.com |
||||||
|
* |
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
||||||
|
*/ |
||||||
|
class OAuth |
||||||
|
{ |
||||||
|
/** |
||||||
|
* An instance of the League OAuth Client Provider. |
||||||
|
* |
||||||
|
* @var AbstractProvider |
||||||
|
*/ |
||||||
|
protected $provider; |
||||||
|
|
||||||
|
/** |
||||||
|
* The current OAuth access token. |
||||||
|
* |
||||||
|
* @var AccessToken |
||||||
|
*/ |
||||||
|
protected $oauthToken; |
||||||
|
|
||||||
|
/** |
||||||
|
* The user's email address, usually used as the login ID |
||||||
|
* and also the from address when sending email. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
protected $oauthUserEmail = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* The client secret, generated in the app definition of the service you're connecting to. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
protected $oauthClientSecret = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* The client ID, generated in the app definition of the service you're connecting to. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
protected $oauthClientId = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* The refresh token, used to obtain new AccessTokens. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
protected $oauthRefreshToken = ''; |
||||||
|
|
||||||
|
/** |
||||||
|
* OAuth constructor. |
||||||
|
* |
||||||
|
* @param array $options Associative array containing |
||||||
|
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements |
||||||
|
*/ |
||||||
|
public function __construct($options) |
||||||
|
{ |
||||||
|
$this->provider = $options['provider']; |
||||||
|
$this->oauthUserEmail = $options['userName']; |
||||||
|
$this->oauthClientSecret = $options['clientSecret']; |
||||||
|
$this->oauthClientId = $options['clientId']; |
||||||
|
$this->oauthRefreshToken = $options['refreshToken']; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get a new RefreshToken. |
||||||
|
* |
||||||
|
* @return RefreshToken |
||||||
|
*/ |
||||||
|
protected function getGrant() |
||||||
|
{ |
||||||
|
return new RefreshToken(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get a new AccessToken. |
||||||
|
* |
||||||
|
* @return AccessToken |
||||||
|
*/ |
||||||
|
protected function getToken() |
||||||
|
{ |
||||||
|
return $this->provider->getAccessToken( |
||||||
|
$this->getGrant(), |
||||||
|
['refresh_token' => $this->oauthRefreshToken] |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate a base64-encoded OAuth token. |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function getOauth64() |
||||||
|
{ |
||||||
|
// Get a new token if it's not available or has expired |
||||||
|
if (null === $this->oauthToken or $this->oauthToken->hasExpired()) { |
||||||
|
$this->oauthToken = $this->getToken(); |
||||||
|
} |
||||||
|
|
||||||
|
return base64_encode( |
||||||
|
'user=' . |
||||||
|
$this->oauthUserEmail . |
||||||
|
"\001auth=Bearer " . |
||||||
|
$this->oauthToken . |
||||||
|
"\001\001" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,419 @@ |
|||||||
|
<?php |
||||||
|
/** |
||||||
|
* PHPMailer POP-Before-SMTP Authentication Class. |
||||||
|
* PHP Version 5.5. |
||||||
|
* |
||||||
|
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project |
||||||
|
* |
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> |
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> |
||||||
|
* @author Brent R. Matzelle (original founder) |
||||||
|
* @copyright 2012 - 2017 Marcus Bointon |
||||||
|
* @copyright 2010 - 2012 Jim Jagielski |
||||||
|
* @copyright 2004 - 2009 Andy Prevost |
||||||
|
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License |
||||||
|
* @note This program is distributed in the hope that it will be useful - WITHOUT |
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. |
||||||
|
*/ |
||||||
|
|
||||||
|
namespace PHPMailer\PHPMailer; |
||||||
|
|
||||||
|
/** |
||||||
|
* PHPMailer POP-Before-SMTP Authentication Class. |
||||||
|
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication. |
||||||
|
* 1) This class does not support APOP authentication. |
||||||
|
* 2) Opening and closing lots of POP3 connections can be quite slow. If you need |
||||||
|
* to send a batch of emails then just perform the authentication once at the start, |
||||||
|
* and then loop through your mail sending script. Providing this process doesn't |
||||||
|
* take longer than the verification period lasts on your POP3 server, you should be fine. |
||||||
|
* 3) This is really ancient technology; you should only need to use it to talk to very old systems. |
||||||
|
* 4) This POP3 class is deliberately lightweight and incomplete, and implements just |
||||||
|
* enough to do authentication. |
||||||
|
* If you want a more complete class there are other POP3 classes for PHP available. |
||||||
|
* |
||||||
|
* @author Richard Davey (original author) <rich@corephp.co.uk> |
||||||
|
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk> |
||||||
|
* @author Jim Jagielski (jimjag) <jimjag@gmail.com> |
||||||
|
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net> |
||||||
|
*/ |
||||||
|
class POP3 |
||||||
|
{ |
||||||
|
/** |
||||||
|
* The POP3 PHPMailer Version number. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
const VERSION = '6.0.5'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Default POP3 port number. |
||||||
|
* |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
const DEFAULT_PORT = 110; |
||||||
|
|
||||||
|
/** |
||||||
|
* Default timeout in seconds. |
||||||
|
* |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
const DEFAULT_TIMEOUT = 30; |
||||||
|
|
||||||
|
/** |
||||||
|
* Debug display level. |
||||||
|
* Options: 0 = no, 1+ = yes. |
||||||
|
* |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
public $do_debug = 0; |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 mail server hostname. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $host; |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 port number. |
||||||
|
* |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
public $port; |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 Timeout Value in seconds. |
||||||
|
* |
||||||
|
* @var int |
||||||
|
*/ |
||||||
|
public $tval; |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 username. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $username; |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 password. |
||||||
|
* |
||||||
|
* @var string |
||||||
|
*/ |
||||||
|
public $password; |
||||||
|
|
||||||
|
/** |
||||||
|
* Resource handle for the POP3 connection socket. |
||||||
|
* |
||||||
|
* @var resource |
||||||
|
*/ |
||||||
|
protected $pop_conn; |
||||||
|
|
||||||
|
/** |
||||||
|
* Are we connected? |
||||||
|
* |
||||||
|
* @var bool |
||||||
|
*/ |
||||||
|
protected $connected = false; |
||||||
|
|
||||||
|
/** |
||||||
|
* Error container. |
||||||
|
* |
||||||
|
* @var array |
||||||
|
*/ |
||||||
|
protected $errors = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Line break constant. |
||||||
|
*/ |
||||||
|
const LE = "\r\n"; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple static wrapper for all-in-one POP before SMTP. |
||||||
|
* |
||||||
|
* @param string $host The hostname to connect to |
||||||
|
* @param int|bool $port The port number to connect to |
||||||
|
* @param int|bool $timeout The timeout value |
||||||
|
* @param string $username |
||||||
|
* @param string $password |
||||||
|
* @param int $debug_level |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
*/ |
||||||
|
public static function popBeforeSmtp( |
||||||
|
$host, |
||||||
|
$port = false, |
||||||
|
$timeout = false, |
||||||
|
$username = '', |
||||||
|
$password = '', |
||||||
|
$debug_level = 0 |
||||||
|
) { |
||||||
|
$pop = new self(); |
||||||
|
|
||||||
|
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Authenticate with a POP3 server. |
||||||
|
* A connect, login, disconnect sequence |
||||||
|
* appropriate for POP-before SMTP authorisation. |
||||||
|
* |
||||||
|
* @param string $host The hostname to connect to |
||||||
|
* @param int|bool $port The port number to connect to |
||||||
|
* @param int|bool $timeout The timeout value |
||||||
|
* @param string $username |
||||||
|
* @param string $password |
||||||
|
* @param int $debug_level |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
*/ |
||||||
|
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0) |
||||||
|
{ |
||||||
|
$this->host = $host; |
||||||
|
// If no port value provided, use default |
||||||
|
if (false === $port) { |
||||||
|
$this->port = static::DEFAULT_PORT; |
||||||
|
} else { |
||||||
|
$this->port = (int) $port; |
||||||
|
} |
||||||
|
// If no timeout value provided, use default |
||||||
|
if (false === $timeout) { |
||||||
|
$this->tval = static::DEFAULT_TIMEOUT; |
||||||
|
} else { |
||||||
|
$this->tval = (int) $timeout; |
||||||
|
} |
||||||
|
$this->do_debug = $debug_level; |
||||||
|
$this->username = $username; |
||||||
|
$this->password = $password; |
||||||
|
// Reset the error log |
||||||
|
$this->errors = []; |
||||||
|
// connect |
||||||
|
$result = $this->connect($this->host, $this->port, $this->tval); |
||||||
|
if ($result) { |
||||||
|
$login_result = $this->login($this->username, $this->password); |
||||||
|
if ($login_result) { |
||||||
|
$this->disconnect(); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
// We need to disconnect regardless of whether the login succeeded |
||||||
|
$this->disconnect(); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Connect to a POP3 server. |
||||||
|
* |
||||||
|
* @param string $host |
||||||
|
* @param int|bool $port |
||||||
|
* @param int $tval |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
*/ |
||||||
|
public function connect($host, $port = false, $tval = 30) |
||||||
|
{ |
||||||
|
// Are we already connected? |
||||||
|
if ($this->connected) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
//On Windows this will raise a PHP Warning error if the hostname doesn't exist. |
||||||
|
//Rather than suppress it with @fsockopen, capture it cleanly instead |
||||||
|
set_error_handler([$this, 'catchWarning']); |
||||||
|
|
||||||
|
if (false === $port) { |
||||||
|
$port = static::DEFAULT_PORT; |
||||||
|
} |
||||||
|
|
||||||
|
// connect to the POP3 server |
||||||
|
$this->pop_conn = fsockopen( |
||||||
|
$host, // POP3 Host |
||||||
|
$port, // Port # |
||||||
|
$errno, // Error Number |
||||||
|
$errstr, // Error Message |
||||||
|
$tval |
||||||
|
); // Timeout (seconds) |
||||||
|
// Restore the error handler |
||||||
|
restore_error_handler(); |
||||||
|
|
||||||
|
// Did we connect? |
||||||
|
if (false === $this->pop_conn) { |
||||||
|
// It would appear not... |
||||||
|
$this->setError( |
||||||
|
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr" |
||||||
|
); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// Increase the stream time-out |
||||||
|
stream_set_timeout($this->pop_conn, $tval, 0); |
||||||
|
|
||||||
|
// Get the POP3 server response |
||||||
|
$pop3_response = $this->getResponse(); |
||||||
|
// Check for the +OK |
||||||
|
if ($this->checkResponse($pop3_response)) { |
||||||
|
// The connection is established and the POP3 server is talking |
||||||
|
$this->connected = true; |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Log in to the POP3 server. |
||||||
|
* Does not support APOP (RFC 2828, 4949). |
||||||
|
* |
||||||
|
* @param string $username |
||||||
|
* @param string $password |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
*/ |
||||||
|
public function login($username = '', $password = '') |
||||||
|
{ |
||||||
|
if (!$this->connected) { |
||||||
|
$this->setError('Not connected to POP3 server'); |
||||||
|
} |
||||||
|
if (empty($username)) { |
||||||
|
$username = $this->username; |
||||||
|
} |
||||||
|
if (empty($password)) { |
||||||
|
$password = $this->password; |
||||||
|
} |
||||||
|
|
||||||
|
// Send the Username |
||||||
|
$this->sendString("USER $username" . static::LE); |
||||||
|
$pop3_response = $this->getResponse(); |
||||||
|
if ($this->checkResponse($pop3_response)) { |
||||||
|
// Send the Password |
||||||
|
$this->sendString("PASS $password" . static::LE); |
||||||
|
$pop3_response = $this->getResponse(); |
||||||
|
if ($this->checkResponse($pop3_response)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Disconnect from the POP3 server. |
||||||
|
*/ |
||||||
|
public function disconnect() |
||||||
|
{ |
||||||
|
$this->sendString('QUIT'); |
||||||
|
//The QUIT command may cause the daemon to exit, which will kill our connection |
||||||
|
//So ignore errors here |
||||||
|
try { |
||||||
|
@fclose($this->pop_conn); |
||||||
|
} catch (Exception $e) { |
||||||
|
//Do nothing |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get a response from the POP3 server. |
||||||
|
* |
||||||
|
* @param int $size The maximum number of bytes to retrieve |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
protected function getResponse($size = 128) |
||||||
|
{ |
||||||
|
$response = fgets($this->pop_conn, $size); |
||||||
|
if ($this->do_debug >= 1) { |
||||||
|
echo 'Server -> Client: ', $response; |
||||||
|
} |
||||||
|
|
||||||
|
return $response; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Send raw data to the POP3 server. |
||||||
|
* |
||||||
|
* @param string $string |
||||||
|
* |
||||||
|
* @return int |
||||||
|
*/ |
||||||
|
protected function sendString($string) |
||||||
|
{ |
||||||
|
if ($this->pop_conn) { |
||||||
|
if ($this->do_debug >= 2) { //Show client messages when debug >= 2 |
||||||
|
echo 'Client -> Server: ', $string; |
||||||
|
} |
||||||
|
|
||||||
|
return fwrite($this->pop_conn, $string, strlen($string)); |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Checks the POP3 server response. |
||||||
|
* Looks for for +OK or -ERR. |
||||||
|
* |
||||||
|
* @param string $string |
||||||
|
* |
||||||
|
* @return bool |
||||||
|
*/ |
||||||
|
protected function checkResponse($string) |
||||||
|
{ |
||||||
|
if (substr($string, 0, 3) !== '+OK') { |
||||||
|
$this->setError("Server reported an error: $string"); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add an error to the internal error store. |
||||||
|
* Also display debug output if it's enabled. |
||||||
|
* |
||||||
|
* @param string $error |
||||||
|
*/ |
||||||
|
protected function setError($error) |
||||||
|
{ |
||||||
|
$this->errors[] = $error; |
||||||
|
if ($this->do_debug >= 1) { |
||||||
|
echo '<pre>'; |
||||||
|
foreach ($this->errors as $e) { |
||||||
|
print_r($e); |
||||||
|
} |
||||||
|
echo '</pre>'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get an array of error messages, if any. |
||||||
|
* |
||||||
|
* @return array |
||||||
|
*/ |
||||||
|
public function getErrors() |
||||||
|
{ |
||||||
|
return $this->errors; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* POP3 connection error handler. |
||||||
|
* |
||||||
|
* @param int $errno |
||||||
|
* @param string $errstr |
||||||
|
* @param string $errfile |
||||||
|
* @param int $errline |
||||||
|
*/ |
||||||
|
protected function catchWarning($errno, $errstr, $errfile, $errline) |
||||||
|
{ |
||||||
|
$this->setError( |
||||||
|
'Connecting to the POP3 server raised a PHP warning:' . |
||||||
|
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,18 @@ |
|||||||
|
<table style="width:99.8%;height:99.8%"> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td style="background:#fafafa url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAy0lEQVQY0x2PsQtAYBDFP1keKZfBKIqNycCERUkMKLuSgZnRarIpJX8s3zfcDe9+794du+8bRVHQOI4wDAOmaULTNDDGYFkWMVVVQUTQdZ3iOMZxHCjLElVV0TRNYHVdC7ptW6RpSn3f4wdJkiTs+w6WJAl4DcOAbdugKAq974umaRAEARgXn+cRW3zfFxuiKCJZloXGHMeBbdv4Beq6Duu6Issy7iYB8Jbnucg8zxPLsggnj/zvIxaGIXmeB9d1wSE+nOeZf4HruvABUtou5ypjMF4AAAAASUVORK5CYII=)"> |
||||||
|
<div style="border-radius:10px;font-size:13px;color:#555;width:666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB','微软雅黑','Microsoft Yahei',Tahoma,Helvetica,Arial,SimSun,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background:#fff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 1px 5px rgba(0,0,0,.15)"> |
||||||
|
<div style="width:100%;background:#49BDAD;color:#fff;border-radius:10px 10px 0 0;background-image:-moz-linear-gradient(0deg,#43c6b8,#ffd1f4);background-image:-webkit-linear-gradient(0deg,#43c6b8,#ffd1f4);height:66px"><p style="font-size:15px;word-break:break-all;padding:23px 32px;margin:0;background-color:hsla(0,0%,100%,.4);border-radius:10px 10px 0 0">您在 [<a href="{blogUrl}" style="text-decoration:none;color:#fff" target="_blank">{blogName}</a>] 的评论已通过审核!</p></div> |
||||||
|
<div style="margin:40px auto;width:90%"> |
||||||
|
<p>{author},您曾在文章《<a href="{permalink}" style="text-decoration:none;color:#12addb" target="_blank">{title}</a>》上发表评论:</p> |
||||||
|
<p style="background:#fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 2px 5px rgba(0,0,0,.15);margin:20px 0;padding:15px;border-radius:5px;font-size:14px;color:#555">{text}</p> |
||||||
|
<p>目前您的评论已通过审核!</p> |
||||||
|
<p>请注意:此邮件由 <a href="{blogUrl}" style="color:#12addb" target="_blank">{blogName}</a> 自动发送,请勿直接回复。</p> |
||||||
|
<p>若此邮件不是您请求的,请忽略并删除!</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
@ -0,0 +1,17 @@ |
|||||||
|
<table style="width:99.8%;height:99.8%"> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td style="background:#fafafa url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAy0lEQVQY0x2PsQtAYBDFP1keKZfBKIqNycCERUkMKLuSgZnRarIpJX8s3zfcDe9+794du+8bRVHQOI4wDAOmaULTNDDGYFkWMVVVQUTQdZ3iOMZxHCjLElVV0TRNYHVdC7ptW6RpSn3f4wdJkiTs+w6WJAl4DcOAbdugKAq974umaRAEARgXn+cRW3zfFxuiKCJZloXGHMeBbdv4Beq6Duu6Issy7iYB8Jbnucg8zxPLsggnj/zvIxaGIXmeB9d1wSE+nOeZf4HruvABUtou5ypjMF4AAAAASUVORK5CYII=)"> |
||||||
|
<div style="border-radius:10px;font-size:13px;color:#555;width:666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB','微软雅黑','Microsoft Yahei',Tahoma,Helvetica,Arial,SimSun,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background:#fff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 1px 5px rgba(0,0,0,.15)"> |
||||||
|
<div style="width:100%;background:#49BDAD;color:#fff;border-radius:10px 10px 0 0;background-image:-moz-linear-gradient(0deg,#43c6b8,#ffd1f4);background-image:-webkit-linear-gradient(0deg,#43c6b8,#ffd1f4);height:66px"><p style="font-size:15px;word-break:break-all;padding:23px 32px;margin:0;background-color:hsla(0,0%,100%,.4);border-radius:10px 10px 0 0">您在 [<a href="{blogUrl}" style="text-decoration:none;color:#fff" target="_blank">{blogName}</a>] 发表的文章有新评论!</p></div> |
||||||
|
<div style="margin:40px auto;width:90%"> |
||||||
|
<p>{author} 在您的《<a href="{permalink}" style="text-decoration:none;color:#12addb" target="_blank">{title}</a>》上发表评论:</p> |
||||||
|
<p style="background:#fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 2px 5px rgba(0,0,0,.15);margin:20px 0;padding:15px;border-radius:5px;font-size:14px;color:#555">{text}</p> |
||||||
|
<p>请注意:此邮件由 <a href="{blogUrl}" style="color:#12addb" target="_blank">{blogName}</a> 自动发送,请勿直接回复。</p> |
||||||
|
<p>若此邮件不是您请求的,请忽略并删除!</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
@ -0,0 +1,60 @@ |
|||||||
|
<div style="background:#ececec;width: 100%;padding: 50px 0;text-align:center;"> |
||||||
|
<div style="background:#fff;width:750px;text-align:left;position:relative;margin:0 auto;font-size:14px;line-height:1.5;"> |
||||||
|
<div style="zoom:1;padding:25px 40px;background:#518bcb; border-bottom:1px solid #467ec3;"> |
||||||
|
<h1 style="color:#fff; font-size:25px;line-height:30px; margin:0;"><a href="{blogurl}" |
||||||
|
style="text-decoration: none;color: #FFF;">您在 |
||||||
|
[{blogname}] 的密码找回申请!</a></h1> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div style="padding:35px 40px 30px;"> |
||||||
|
<h2 style="font-size:18px;margin:5px 0;"><span |
||||||
|
style="color: rgb(186, 76, 50); font-family:微软雅黑, verdana, arial; line-height: 23.3999996185303px;">{mail}</span>, |
||||||
|
您好!</h2> |
||||||
|
|
||||||
|
<p style="color:#313131;line-height:20px;font-size:15px;margin:20px 0;">您在 [{blogname}] 提交了找回密码申请, |
||||||
|
请核对下方表内信息并点击链接修改密码:</p> |
||||||
|
|
||||||
|
<table cellspacing="0" |
||||||
|
style="font-size:14px;text-align:center;border:1px solid #ccc;table-layout:fixed;width:500px;"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;" |
||||||
|
width="280px;">邮箱地址 |
||||||
|
</th> |
||||||
|
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;" |
||||||
|
width="270px;">申请时间 |
||||||
|
</th> |
||||||
|
<th style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:normal;color:#a0a0a0;background:#eee;border-color:#dfdfdf;" |
||||||
|
width="110px;">操作 |
||||||
|
</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;"> |
||||||
|
{mail} |
||||||
|
</td> |
||||||
|
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;"> |
||||||
|
{sendtime} |
||||||
|
</td> |
||||||
|
<td style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;"> |
||||||
|
<a href="{resetlink}" style="color:#1E5494;text-decoration:none;vertical-align:middle;" |
||||||
|
target="_blank">{resetlink}</a></td> |
||||||
|
</tr> |
||||||
|
<tr> |
||||||
|
<td colspan="3" |
||||||
|
style="padding:5px 0;text-indent:8px;border:1px solid #eee;border-width:0 1px 1px 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#FF0000;font-weight:bold"> |
||||||
|
重置密码链接有效时间为 "{expire}" 分钟, 请在此时间内进行密码重置 |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
|
||||||
|
|
||||||
|
<div style="font-size:13px;color:#a0a0a0;padding-top:10px">请注意:此邮件由 <a href="{blogurl}" target="_blank" |
||||||
|
title="{blogname}">{blogname}</a> 自动发送,请勿直接回复。<br/> |
||||||
|
若此邮件不是您请求的,请忽略并删除! |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
@ -0,0 +1,20 @@ |
|||||||
|
<table style="width:99.8%;height:99.8%"> |
||||||
|
<tbody> |
||||||
|
<tr> |
||||||
|
<td style="background:#fafafa url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAy0lEQVQY0x2PsQtAYBDFP1keKZfBKIqNycCERUkMKLuSgZnRarIpJX8s3zfcDe9+794du+8bRVHQOI4wDAOmaULTNDDGYFkWMVVVQUTQdZ3iOMZxHCjLElVV0TRNYHVdC7ptW6RpSn3f4wdJkiTs+w6WJAl4DcOAbdugKAq974umaRAEARgXn+cRW3zfFxuiKCJZloXGHMeBbdv4Beq6Duu6Issy7iYB8Jbnucg8zxPLsggnj/zvIxaGIXmeB9d1wSE+nOeZf4HruvABUtou5ypjMF4AAAAASUVORK5CYII=)"> |
||||||
|
<div style="border-radius:10px;font-size:13px;color:#555;width:666px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB','微软雅黑','Microsoft Yahei',Tahoma,Helvetica,Arial,SimSun,sans-serif;margin:50px auto;border:1px solid #eee;max-width:100%;background:#fff repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 1px 5px rgba(0,0,0,.15)"> |
||||||
|
<div style="width:100%;background:#49BDAD;color:#fff;border-radius:10px 10px 0 0;background-image:-moz-linear-gradient(0deg,#43c6b8,#ffd1f4);background-image:-webkit-linear-gradient(0deg,#43c6b8,#ffd1f4);height:66px"><p style="font-size:15px;word-break:break-all;padding:23px 32px;margin:0;background-color:hsla(0,0%,100%,.4);border-radius:10px 10px 0 0">您在 [<a href="{blogUrl}" style="text-decoration:none;color:#fff" target="_blank">{blogName}</a>] 的评论有了新的回复!</p></div> |
||||||
|
<div style="margin:40px auto;width:90%"> |
||||||
|
<p>{author},您曾在文章《<a href="{permalink}" style="text-decoration:none;color:#12addb" target="_blank">{title}</a>》上发表评论:</p> |
||||||
|
<p style="background:#fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 2px 5px rgba(0,0,0,.15);margin:20px 0;padding:15px;border-radius:5px;font-size:14px;color:#555">{text}</p> |
||||||
|
<p>{replyAuthor} 给您的回复如下:</p> |
||||||
|
<p style="background:#fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow:0 2px 5px rgba(0,0,0,.15);margin:20px 0;padding:15px;border-radius:5px;font-size:14px;color:#555">{replyText}</p> |
||||||
|
<p>您可以 <a href="{commentUrl}" style="text-decoration:none;color:#12addb" target="_blank">查看回复完整内容</a>,欢迎再次光临 <a href="{blogUrl}" style="text-decoration:none;color:#12addb" target="_blank">{blogName}</a>。</p> |
||||||
|
<p>请注意:此邮件由 <a href="{blogUrl}" style="color:#12addb" target="_blank">{blogName}</a> 自动发送,请勿直接回复。</p> |
||||||
|
<p>若此邮件不是您请求的,请忽略并删除!</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</td> |
||||||
|
</tr> |
||||||
|
</tbody> |
||||||
|
</table> |
@ -1,6 +1 @@ |
|||||||
/** |
.hljs{display:block;overflow-x:auto;padding:.5em}.hljs{color:#00193a}.hljs-keyword,.hljs-selector-tag,.hljs-title,.hljs-section,.hljs-doctag,.hljs-name,.hljs-strong{font-weight:bold}.hljs-comment{color:#738191}.hljs-string,.hljs-title,.hljs-section,.hljs-built_in,.hljs-literal,.hljs-type,.hljs-addition,.hljs-tag,.hljs-quote,.hljs-name,.hljs-selector-id,.hljs-selector-class{color:#0048ab}.hljs-meta,.hljs-subst,.hljs-symbol,.hljs-regexp,.hljs-attribute,.hljs-deletion,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-bullet{color:#4c81c9}.hljs-emphasis{font-style:italic} |
||||||
@author: yourself |
|
||||||
@description: 这里的css代码可以从 https://github.com/isagalaev/highlight.js/tree/master/src/styles 这里面下载。随意选择一个你喜欢的,然后复制在这个文件里。 |
|
||||||
@notice: 记得在后台外观设置——代码高亮样式选择里面选择[自定义]选项,否则这里面的代码是不会生效的 |
|
||||||
@better: 为了减少css文件的大小,你可以先压缩代码再写入该文件 |
|
||||||
*/ |
|
@ -1 +1,42 @@ |
|||||||
function echo(stringA,stringB){var hello="你好";alert("hello world")}.hljs{display:block;overflow-x:auto;padding:.5em;color:black}.hljs-comment,.hljs-quote,.hljs-variable{color:#008000}.hljs-keyword,.hljs-selector-tag,.hljs-built_in,.hljs-name,.hljs-tag{color:#00f}.hljs-string,.hljs-title,.hljs-section,.hljs-attribute,.hljs-literal,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-addition{color:#a31515}.hljs-deletion,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-meta{color:#2b91af}.hljs-doctag{color:#808080}.hljs-attr{color:#f00}.hljs-symbol,.hljs-bullet,.hljs-link{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} |
.hljs { |
||||||
|
display: block; |
||||||
|
overflow-x: auto; |
||||||
|
padding: .5em; |
||||||
|
color: #000 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-comment,.hljs-quote,.hljs-variable { |
||||||
|
color: green |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag { |
||||||
|
color: #00f |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type { |
||||||
|
color: #a31515 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo { |
||||||
|
color: #2b91af |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-doctag { |
||||||
|
color: grey |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-attr { |
||||||
|
color: red |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-bullet,.hljs-link,.hljs-symbol { |
||||||
|
color: #00b0e8 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-emphasis { |
||||||
|
font-style: italic |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-strong { |
||||||
|
font-weight: 700 |
||||||
|
} |
||||||
|
@ -1,6 +1 @@ |
|||||||
/** |
.hljs{display:block;overflow-x:auto;padding:.5em}.hljs{color:#00193a}.hljs-keyword,.hljs-selector-tag,.hljs-title,.hljs-section,.hljs-doctag,.hljs-name,.hljs-strong{font-weight:bold}.hljs-comment{color:#738191}.hljs-string,.hljs-title,.hljs-section,.hljs-built_in,.hljs-literal,.hljs-type,.hljs-addition,.hljs-tag,.hljs-quote,.hljs-name,.hljs-selector-id,.hljs-selector-class{color:#0048ab}.hljs-meta,.hljs-subst,.hljs-symbol,.hljs-regexp,.hljs-attribute,.hljs-deletion,.hljs-variable,.hljs-template-variable,.hljs-link,.hljs-bullet{color:#4c81c9}.hljs-emphasis{font-style:italic} |
||||||
@author: yourself |
|
||||||
@description: 这里的css代码可以从 https://github.com/isagalaev/highlight.js/tree/master/src/styles 这里面下载。随意选择一个你喜欢的,然后复制在这个文件里。 |
|
||||||
@notice: 记得在后台外观设置——代码高亮样式选择里面选择[自定义]选项,否则这里面的代码是不会生效的 |
|
||||||
@better: 为了减少css文件的大小,你可以先压缩代码再写入该文件 |
|
||||||
*/ |
|
@ -1 +1,42 @@ |
|||||||
function echo(stringA,stringB){var hello="你好";alert("hello world")}.hljs{display:block;overflow-x:auto;padding:.5em;color:black}.hljs-comment,.hljs-quote,.hljs-variable{color:#008000}.hljs-keyword,.hljs-selector-tag,.hljs-built_in,.hljs-name,.hljs-tag{color:#00f}.hljs-string,.hljs-title,.hljs-section,.hljs-attribute,.hljs-literal,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-addition{color:#a31515}.hljs-deletion,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-meta{color:#2b91af}.hljs-doctag{color:#808080}.hljs-attr{color:#f00}.hljs-symbol,.hljs-bullet,.hljs-link{color:#00b0e8}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold} |
.hljs { |
||||||
|
display: block; |
||||||
|
overflow-x: auto; |
||||||
|
padding: .5em; |
||||||
|
color: #000 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-comment,.hljs-quote,.hljs-variable { |
||||||
|
color: green |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-built_in,.hljs-keyword,.hljs-name,.hljs-selector-tag,.hljs-tag { |
||||||
|
color: #00f |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-addition,.hljs-attribute,.hljs-literal,.hljs-section,.hljs-string,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type { |
||||||
|
color: #a31515 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-deletion,.hljs-meta,.hljs-selector-attr,.hljs-selector-pseudo { |
||||||
|
color: #2b91af |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-doctag { |
||||||
|
color: grey |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-attr { |
||||||
|
color: red |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-bullet,.hljs-link,.hljs-symbol { |
||||||
|
color: #00b0e8 |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-emphasis { |
||||||
|
font-style: italic |
||||||
|
} |
||||||
|
|
||||||
|
.hljs-strong { |
||||||
|
font-weight: 700 |
||||||
|
} |
||||||
|
Loading…
Reference in new issue