diff --git a/README.md b/README.md index 2ea2765..d501df1 100644 --- a/README.md +++ b/README.md @@ -41,13 +41,13 @@ * 書き込み権限がない場合、コマンドプロンプトを管理者権限で起動して作成する * `C:\Program Files\RepostConfirmationCanceler\RepostConfirmationCanceler.ini` のアクセス権を変更し、ユーザー権限での書き込みを許可した上で、以下のような内容を記載する * ``` - [Edge] + [TARGETS] * ``` ## 動作解説 -* ブラウザの拡張機能 RepostConfirmationCanceler が、`RepostConfirmationCanceler.ini`の`[Edge]`セクションに記載されているURLを開いているかを判定する +* ブラウザの拡張機能 RepostConfirmationCanceler が、`RepostConfirmationCanceler.ini`の`[TARGETS]`セクションに記載されているURLを開いているかを判定する * サイトを開いたタイミングと、30秒ごとのポーリングで判定を行う * 指定のURLを開いていた場合、ブラウザの拡張機能が RepostConfirmationCancelerTalk.exe を呼び出す。 * このとき、`Q Edge`というメッセージを送信する diff --git a/RepostConfirmationCanceler/ConfigLoader.cs b/RepostConfirmationCanceler/ConfigLoader.cs index b01be4e..0e889e1 100644 --- a/RepostConfirmationCanceler/ConfigLoader.cs +++ b/RepostConfirmationCanceler/ConfigLoader.cs @@ -11,9 +11,6 @@ namespace RepostConfirmationCanceler internal class Section { public string Name; - public bool Disabled = false; - public bool WarningWhenCloseDialog = false; - public StringBuilder ExcludeGroups = new StringBuilder(); public StringBuilder Excludes = new StringBuilder(); public StringBuilder Patterns = new StringBuilder(); @@ -27,12 +24,8 @@ internal class Config { public bool IgnoreQueryString = false; public bool OnlyMainFrame = false; + public bool WarningWhenCloseDialog = false; public List
SectionList = new List
(); - - public Section GetEdgeSection() - { - return SectionList.FirstOrDefault(_ => _.Name.ToLowerInvariant() == "[edge]"); - } } internal static class ConfigLoader @@ -120,29 +113,9 @@ internal static Config ParseConf(string data) case '@': if (global) { - if (line == "@TOP_PAGE_ONLY") - { - conf.IgnoreQueryString = true; - } - else if (line == "@ONLY_MAIN_FRAME") - { - conf.OnlyMainFrame = true; - } - } - else if (section != null) - { - if (line == "@DISABLED") - { - section.Disabled = true; - } - else if (line == "@WARNING_WHEN_CLOSE_DIALOG") - { - section.WarningWhenCloseDialog = true; - } - else if (line.StartsWith("@EXCLUDE_GROUP:")) + if (line == "@WARNING_WHEN_CLOSE_DIALOG") { - section.ExcludeGroups.Append(line.Substring("@EXCLUDE_GROUP:".Length)); - section.ExcludeGroups.Append('\n'); + conf.WarningWhenCloseDialog = true; } } break; diff --git a/RepostConfirmationCanceler/EdgeConfirmationDialogCanceler.cs b/RepostConfirmationCanceler/EdgeConfirmationDialogCanceler.cs index 9e9fdcb..92da2a1 100644 --- a/RepostConfirmationCanceler/EdgeConfirmationDialogCanceler.cs +++ b/RepostConfirmationCanceler/EdgeConfirmationDialogCanceler.cs @@ -107,8 +107,7 @@ internal static void CancelDialog(RuntimeContext context, AutomationElement edge return; } - var edgeConfig = context.Config.GetEdgeSection(); - if (edgeConfig?.WarningWhenCloseDialog ?? false) + if (context.Config?.WarningWhenCloseDialog ?? false) { context.Logger.Log($"Display warning dialog"); ShowWarningDialog(); diff --git a/RepostConfirmationCancelerTalk/cb_config.c b/RepostConfirmationCancelerTalk/cb_config.c index 0b92000..7bf3123 100644 --- a/RepostConfirmationCancelerTalk/cb_config.c +++ b/RepostConfirmationCancelerTalk/cb_config.c @@ -25,16 +25,13 @@ */ struct section { char name[16]; - int disabled; - struct strbuf exclude_groups; struct strbuf patterns; struct strbuf excludes; struct section *next; /* linked list */ }; struct config { - int only_main_frame; - int ignore_query_string; + int warning_when_close_dialog; struct section *section; }; @@ -64,9 +61,9 @@ static struct section *new_section(char *line) * You can define variables/URLs in each section like this: * * [GLOBAL] - * @TOP_PAGE_ONLY + * @WARNING_WHEN_CLOSE_DIALOG * - * [Edge] + * [TARGETS] * https://example.com* * -https://test.example.com* * @@ -77,7 +74,6 @@ static void parse_conf(char *data, struct config *conf) { char *line; int global; - int _default; struct section *section; struct section **indirect = &conf->section; @@ -89,14 +85,10 @@ static void parse_conf(char *data, struct config *conf) break; case '[': global = 0; - _default = 0; if (strcmp(line, "[GLOBAL]") == 0) { global = 1; } - else if (strcmp(line, "[Default]") == 0) { - _default = 1; - } else { section = new_section(line); *indirect = section; @@ -105,20 +97,9 @@ static void parse_conf(char *data, struct config *conf) break; case '@': if (global) { - if (strcmp(line, "@TOP_PAGE_ONLY") == 0) { - conf->ignore_query_string = 1; - } - else if (strcmp(line, "@ONLY_MAIN_FRAME") == 0) { - conf->only_main_frame = 1; - } - } - else if (section) { - if (strcmp(line, "@DISABLED") == 0) { - section->disabled = 1; - } - else if (strstr(line, "@EXCLUDE_GROUP:") == line) { - strbuf_concat(§ion->exclude_groups, line + strlen("@EXCLUDE_GROUP:")); - strbuf_putchar(§ion->exclude_groups, '\n'); + if (line == "@WARNING_WHEN_CLOSE_DIALOG") + { + conf->warning_when_close_dialog = 1; } } break; @@ -150,22 +131,6 @@ static char *dump_section(struct section *section) strbuf_concat_jsonstr(&sb, section->name, strlen(section->name)); strbuf_putchar(&sb, ','); - strbuf_concat(&sb, "\"ExcludeGroups\":["); - if (section->exclude_groups.buf) { - ptr = section->exclude_groups.buf; - need_comma = 0; - while (*ptr) { - if (need_comma) - strbuf_putchar(&sb, ','); - - end = strchr(ptr, '\n'); - strbuf_concat_jsonstr(&sb, ptr, end - ptr); - need_comma = 1; - ptr = end + 1; - } - } - strbuf_concat(&sb, "],"); - /* URLPatterns */ strbuf_concat(&sb, "\"Patterns\":["); if (section->patterns.buf) { @@ -211,14 +176,9 @@ static char *dump_json(struct config *conf) char *json; int need_comma; - /* OnlyMainFrame */ - strbuf_concat(&sb, "{\"OnlyMainFrame\":"); - strbuf_concat(&sb, _itoa(conf->only_main_frame, buf, 10)); - strbuf_putchar(&sb, ','); - - /* IgnoreQueryString */ - strbuf_concat(&sb, "\"IgnoreQueryString\":"); - strbuf_concat(&sb, _itoa(conf->ignore_query_string, buf, 10)); + /* WarningWhenCloseDialog */ + strbuf_concat(&sb, "{\"WarningWhenCloseDialog\":"); + strbuf_concat(&sb, _itoa(conf->warning_when_close_dialog, buf, 10)); strbuf_putchar(&sb, ','); /* Sections */ @@ -227,8 +187,8 @@ static char *dump_json(struct config *conf) section = conf->section; need_comma = 0; while (section) { - /* Disabled or no pattern defined */ - if (section->disabled || section->patterns.buf == NULL) { + /* no pattern defined */ + if (section->patterns.buf == NULL) { section = section->next; continue; } @@ -336,7 +296,6 @@ int cb_config(char *cmd) section = conf.section; while (section) { next = section->next; - free(section->exclude_groups.buf); free(section->patterns.buf); free(section->excludes.buf); free(section); diff --git a/Resources/RepostConfirmationCanceler.ini b/Resources/RepostConfirmationCanceler.ini index 368c3d9..cd2c849 100644 --- a/Resources/RepostConfirmationCanceler.ini +++ b/Resources/RepostConfirmationCanceler.ini @@ -2,5 +2,5 @@ ## Configuration File for RepostConfirmationCanceler (ver1.0) ##################################################################### -[Edge] +[TARGETS] * diff --git a/doc/Sources/user-guide.md b/doc/Sources/user-guide.md index 041f382..9f0fffe 100644 --- a/doc/Sources/user-guide.md +++ b/doc/Sources/user-guide.md @@ -355,27 +355,62 @@ RepostConfirmationCancelerセットアップ先のRepostConfirmationCanceler.ini 例) `C:\Program Files\RepostConfirmationCanceler\RepostConfirmationCanceler.ini` +## 設定ファイルの書式 + +設定ファイルは、以下のように`[GLOBAL]`セクションと`[TARGETS]`セクションに分かれています。 + +``` +[GLOBAL] +@WARNING_WHEN_CLOSE_DIALOG + +[TARGETS] +https://example.com/* +-https://example.com/test/ +``` + +各セクションに対して、必要な項目を設定します。 + ## 設定項目の一覧 -Edgeでの動作については、`[Edge]`セクションに記載します。 +### 一般設定 + +一般設定については、`[GLOBAL]`セクションに記載します。 | 項目 | 設定内容 | 既定 | -|------------|---------------------------------------|------| -| 対象URL一覧(書式は後述) | 「フォームを再送信しますか?」ダイアログをキャンセルするURL|*(すべてのURL)| | @WARNING_WHEN_CLOSE_DIALOG | 「フォームを再送信しますか?」ダイアログをキャンセルしたとき、追加の警告ダイアログを表示する | 無効 | +#### @WARNING_WHEN_CLOSE_DIALOG + +フォームを再送信しますか?」ダイアログをキャンセルしたとき、以下のような追加の警告ダイアログを表示します。 + +![](user-guide/media/image31.png) + +以下のように値なしのパラメータとして指定します。 + +``` +[GLOBAL] +@WARNING_WHEN_CLOSE_DIALOG +``` + +### 対象URL一覧 + +対象URL一覧については、`[TARGETS]`セクションに記載します。 + +| 項目 | 設定内容 | 既定 | +|------------|---------------------------------------|------| +| 対象URL一覧(書式は後述) | 「フォームを再送信しますか?」ダイアログをキャンセルするURL|*(すべてのURL)| 注: いずれかのタブで対象URLを開いている場合に本プログラムが動作します。実際に開いているURLが対象URLでなくても、別のタブで対象URLを 開いている場合、「フォームを再送信しますか?」ダイアログがキャンセルされます。 -### 対象URL一覧書式 +#### 対象URL一覧書式 対象URL一覧は以下のようにURL全体を改行切りで指定します。 例) ``` -[Edge] +[TARGETS] https://www.clear-code.com/ https://example.com/ ``` @@ -402,26 +437,13 @@ https://example.com/ 例) ``` -[Edge] +[TARGETS] https://example.com/* -https://example.com/test/ ``` これは「`https://example.com/`を含むサイトを対象とするが、`https://example.com/test/`は除外する」という設定です。 -### @WARNING_WHEN_CLOSE_DIALOG - -フォームを再送信しますか?」ダイアログをキャンセルしたとき、以下のような追加の警告ダイアログを表示します。 - -![](user-guide/media/image31.png) - -以下のように値なしのパラメータとして指定します。 - -``` -[Edge] -@WARNING_WHEN_CLOSE_DIALOG -``` - ## グループポリシー(GPO)を利用した設定ファイルの配布手順 ADに所属している端末の設定を強制する場合、グループポリシー(GPO)で設定ファイルを配布することで強制します。 diff --git a/doc/verify/sources/TestTools/Senarios/scenario1.ini b/doc/verify/sources/TestTools/Senarios/scenario1.ini index f34f5a9..59ea4fd 100644 --- a/doc/verify/sources/TestTools/Senarios/scenario1.ini +++ b/doc/verify/sources/TestTools/Senarios/scenario1.ini @@ -1,2 +1,2 @@ -[Edge] +[TARGETS] * diff --git a/doc/verify/sources/TestTools/Senarios/scenario2.ini b/doc/verify/sources/TestTools/Senarios/scenario2.ini index f59158a..976f231 100644 --- a/doc/verify/sources/TestTools/Senarios/scenario2.ini +++ b/doc/verify/sources/TestTools/Senarios/scenario2.ini @@ -1,3 +1,5 @@ -[Edge] +[GLOBAL] @WARNING_WHEN_CLOSE_DIALOG + +[TARGETS] * diff --git a/doc/verify/sources/TestTools/Senarios/scenario3.ini b/doc/verify/sources/TestTools/Senarios/scenario3.ini index 2ca47cc..b341c25 100644 --- a/doc/verify/sources/TestTools/Senarios/scenario3.ini +++ b/doc/verify/sources/TestTools/Senarios/scenario3.ini @@ -1,4 +1,4 @@ -[Edge] +[TARGETS] *://example.com/jp* *://example.com/us/??/ https://www.clear-code.com/ diff --git a/webextensions/edge/background.js b/webextensions/edge/background.js index c18cfd2..eb46b16 100644 --- a/webextensions/edge/background.js +++ b/webextensions/edge/background.js @@ -20,41 +20,21 @@ const ALARM_MINUTES = 0.5; * true */ function wildcmp(wild, string) { - let i = 0; - let j = 0; - let mp, cp; - - while ((j < string.length) && (wild[i] != '*')) { - if ((wild[i] != string[j]) && (wild[i] != '?')) { - return 0; - } - i += 1; - j += 1; - } - while (j < string.length) { - if (wild[i] == '*') { - i += 1; - - if (i == wild.length) { - return 1; - } - mp = i; - cp = j + 1 - } else if ((wild[i] == string[j]) || (wild[i] == '?')) { - i += 1; - j += 1; - } else { - i = mp; - j = cp; - cp += 1; - } - } - while (wild[i] == '*' && i < wild.length) { - i += 1; + if(!wild || !string) { + return false; } - return i >= wild.length; + const pattern = wildcardToRegexp(wild); + const regex = new RegExp(`^${pattern}$`, "i"); + return regex.test(string); }; +function wildcardToRegexp(source) { + // https://stackoverflow.com/questions/6300183/sanitize-string-of-regex-characters-before-regexp-build + const sanitized = source.replace(/[#-.]|[[-^]|[?|{}]/g, "\\$&"); + const wildcardAccepted = sanitized.replace(/\\\*/g, ".*").replace(/\\\?/g, "."); + return wildcardAccepted; +} + /* * Observe WebRequests with config fetched from RepostConfirmationCanceler. * @@ -102,8 +82,8 @@ const RepostConfirmationCancelerTalkClient = { }, /* - * Request redirection to Native Messaging Hosts. - * * Request Example: "Q edge https://example.com/". + * Request monitoring to Native Messaging Hosts. + * * Request Example: "Q edge". */ startMonitoring() { const query = new String('Q ' + BROWSER); @@ -112,7 +92,7 @@ const RepostConfirmationCancelerTalkClient = { }, match(section, url) { - for (let pattern of (section.URLExcludePatterns || section.Excludes || [])) { + for (let pattern of (section.Excludes || [])) { if (Array.isArray(pattern)) { pattern = pattern[0]; } @@ -122,7 +102,7 @@ const RepostConfirmationCancelerTalkClient = { } } - for (let pattern of (section.URLPatterns || section.Patterns || [])) { + for (let pattern of (section.Patterns || [])) { if (Array.isArray(pattern)) { pattern = pattern[0]; } @@ -134,17 +114,6 @@ const RepostConfirmationCancelerTalkClient = { return false; }, - getBrowserName(section) { - const name = section.Name.toLowerCase(); - - /* Guess the browser name from the executable path */ - if (name.match(/^custom/i)) { - if (section.Path.match(RegExp(BROWSER, 'i'))) - return BROWSER; - } - return name; - }, - handleURL(config, url){ if (!url) { console.log(`* Empty URL found`); @@ -155,12 +124,15 @@ const RepostConfirmationCancelerTalkClient = { console.log(`* Ignore non-HTTP/HTTPS URL ${url}`); return false; } - const urlToMatch = config.IgnoreQueryString ? url.replace(/\?.*/, '') : url; + const urlToMatch = url; console.log(`* Lookup sections for ${urlToMatch}`); for (const section of config.Sections) { + if (section.Name.toLowerCase() !== "targets") + { + continue; + } console.log(`handleURL: check for section ${section.Name} (${JSON.stringify(section)})`); - if (this.match(section, urlToMatch)) { console.log(` => unmatched`); this.startMonitoring();