From fca48b2a816fcef6ad17ccb0c31a2c9a15c31e54 Mon Sep 17 00:00:00 2001 From: naskya Date: Sun, 14 Apr 2024 20:29:44 +0900 Subject: [PATCH] refactor (backend): port safe-for-sql, sql-like-escape to backend-rs --- packages/backend-rs/index.d.ts | 2 ++ packages/backend-rs/index.js | 4 ++- packages/backend-rs/src/misc/escape_sql.rs | 36 +++++++++++++++++++ packages/backend-rs/src/misc/mod.rs | 1 + packages/backend/src/misc/safe-for-sql.ts | 3 -- packages/backend/src/misc/sql-like-escape.ts | 3 -- .../api/endpoints/admin/emoji/list-remote.ts | 3 +- .../server/api/endpoints/admin/emoji/list.ts | 4 +-- .../server/api/endpoints/admin/show-users.ts | 2 +- .../server/api/endpoints/channels/search.ts | 2 +- .../api/endpoints/federation/instances.ts | 3 +- .../server/api/endpoints/hashtags/search.ts | 2 +- .../server/api/endpoints/hashtags/trend.ts | 3 +- .../api/endpoints/notes/search-by-tag.ts | 2 +- .../src/server/api/endpoints/notes/search.ts | 4 +-- .../users/search-by-username-and-host.ts | 2 +- .../src/server/api/endpoints/users/search.ts | 2 +- 17 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 packages/backend-rs/src/misc/escape_sql.rs delete mode 100644 packages/backend/src/misc/safe-for-sql.ts delete mode 100644 packages/backend/src/misc/sql-like-escape.ts diff --git a/packages/backend-rs/index.d.ts b/packages/backend-rs/index.d.ts index 3770056d8f..a9398aacc1 100644 --- a/packages/backend-rs/index.d.ts +++ b/packages/backend-rs/index.d.ts @@ -132,6 +132,8 @@ export function isSelfHost(host?: string | undefined | null): boolean export function isSameOrigin(uri: string): boolean export function extractHost(uri: string): string export function toPuny(host: string): string +export function sqlLikeEscape(src: string): string +export function safeForSql(src: string): boolean /** Convert milliseconds to a human readable string */ export function formatMilliseconds(milliseconds: number): string export function toMastodonId(firefishId: string): string | null diff --git a/packages/backend-rs/index.js b/packages/backend-rs/index.js index 363c858e4a..7a404d6447 100644 --- a/packages/backend-rs/index.js +++ b/packages/backend-rs/index.js @@ -310,7 +310,7 @@ if (!nativeBinding) { throw new Error(`Failed to load native binding`) } -const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, formatMilliseconds, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding +const { readServerConfig, stringToAcct, acctToString, checkWordMute, getFullApAccount, isSelfHost, isSameOrigin, extractHost, toPuny, sqlLikeEscape, safeForSql, formatMilliseconds, toMastodonId, fromMastodonId, fetchMeta, metaToPugArgs, nyaify, hashPassword, verifyPassword, isOldPasswordAlgorithm, AntennaSrcEnum, MutedNoteReasonEnum, NoteVisibilityEnum, NotificationTypeEnum, PageVisibilityEnum, PollNotevisibilityEnum, RelayStatusEnum, UserEmojimodpermEnum, UserProfileFfvisibilityEnum, UserProfileMutingnotificationtypesEnum, initIdGenerator, getTimestamp, genId, secureRndstr } = nativeBinding module.exports.readServerConfig = readServerConfig module.exports.stringToAcct = stringToAcct @@ -321,6 +321,8 @@ module.exports.isSelfHost = isSelfHost module.exports.isSameOrigin = isSameOrigin module.exports.extractHost = extractHost module.exports.toPuny = toPuny +module.exports.sqlLikeEscape = sqlLikeEscape +module.exports.safeForSql = safeForSql module.exports.formatMilliseconds = formatMilliseconds module.exports.toMastodonId = toMastodonId module.exports.fromMastodonId = fromMastodonId diff --git a/packages/backend-rs/src/misc/escape_sql.rs b/packages/backend-rs/src/misc/escape_sql.rs new file mode 100644 index 0000000000..c575e088ce --- /dev/null +++ b/packages/backend-rs/src/misc/escape_sql.rs @@ -0,0 +1,36 @@ +#[crate::export] +pub fn sql_like_escape(src: &str) -> String { + src.replace('%', r"\%").replace('_', r"\_") +} + +#[crate::export] +pub fn safe_for_sql(src: &str) -> bool { + !src.contains([ + '\0', '\x08', '\x09', '\x1a', '\n', '\r', '"', '\'', '\\', '%', + ]) +} + +#[cfg(test)] +mod unit_test { + use super::{safe_for_sql, sql_like_escape}; + use pretty_assertions::assert_eq; + + #[test] + fn sql_like_escape_test() { + assert_eq!(sql_like_escape(""), ""); + assert_eq!(sql_like_escape("abc"), "abc"); + assert_eq!(sql_like_escape("a%bc"), r"a\%bc"); + assert_eq!(sql_like_escape("a呼%吸bc"), r"a呼\%吸bc"); + assert_eq!(sql_like_escape("a呼%吸b%_c"), r"a呼\%吸b\%\_c"); + assert_eq!(sql_like_escape("_اللغة العربية"), r"\_اللغة العربية"); + } + + #[test] + fn safe_for_sql_test() { + assert!(safe_for_sql("123")); + assert!(safe_for_sql("人間")); + assert!(!safe_for_sql("人間\x09")); + assert!(!safe_for_sql("abc\ndef")); + assert!(!safe_for_sql("%something%")); + } +} diff --git a/packages/backend-rs/src/misc/mod.rs b/packages/backend-rs/src/misc/mod.rs index 7f99a67324..74a483ea51 100644 --- a/packages/backend-rs/src/misc/mod.rs +++ b/packages/backend-rs/src/misc/mod.rs @@ -1,6 +1,7 @@ pub mod acct; pub mod check_word_mute; pub mod convert_host; +pub mod escape_sql; pub mod format_milliseconds; pub mod mastodon_id; pub mod meta; diff --git a/packages/backend/src/misc/safe-for-sql.ts b/packages/backend/src/misc/safe-for-sql.ts deleted file mode 100644 index 02eb7f0a26..0000000000 --- a/packages/backend/src/misc/safe-for-sql.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function safeForSql(text: string): boolean { - return !/[\0\x08\x09\x1a\n\r"'\\\%]/g.test(text); -} diff --git a/packages/backend/src/misc/sql-like-escape.ts b/packages/backend/src/misc/sql-like-escape.ts deleted file mode 100644 index 453947d6ec..0000000000 --- a/packages/backend/src/misc/sql-like-escape.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function sqlLikeEscape(s: string) { - return s.replace(/([%_])/g, "\\$1"); -} diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 5c3e19d9e0..9c7a5180d3 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -1,8 +1,7 @@ import define from "@/server/api/define.js"; import { Emojis } from "@/models/index.js"; -import { toPuny } from "backend-rs"; +import { sqlLikeEscape, toPuny } from "backend-rs"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; import { ApiError } from "@/server/api/error.js"; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 434b679608..98a69090db 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -1,8 +1,8 @@ import define from "@/server/api/define.js"; import { Emojis } from "@/models/index.js"; -import { makePaginationQuery } from "../../../common/make-pagination-query.js"; +import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; import type { Emoji } from "@/models/entities/emoji.js"; -//import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +//import { sqlLikeEscape } from "backend-rs"; import { ApiError } from "@/server/api/error.js"; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 1e6ebeda93..8a892c3606 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -1,6 +1,6 @@ import { Users } from "@/models/index.js"; import define from "@/server/api/define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["admin"], diff --git a/packages/backend/src/server/api/endpoints/channels/search.ts b/packages/backend/src/server/api/endpoints/channels/search.ts index b2fab701c5..ed44250a37 100644 --- a/packages/backend/src/server/api/endpoints/channels/search.ts +++ b/packages/backend/src/server/api/endpoints/channels/search.ts @@ -2,7 +2,7 @@ import define from "@/server/api/define.js"; import { Brackets } from "typeorm"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; import { Channels } from "@/models/index.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["channels"], diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 8c021d0e65..362ab098fb 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -1,7 +1,6 @@ import define from "@/server/api/define.js"; import { Instances } from "@/models/index.js"; -import { fetchMeta } from "backend-rs"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { fetchMeta, sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["federation"], diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 1dc1fb4922..8fb5b23f62 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -1,6 +1,6 @@ import define from "@/server/api/define.js"; import { Hashtags } from "@/models/index.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["hashtags"], diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts index 9d31445a42..531a494248 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts @@ -1,9 +1,8 @@ import { Brackets } from "typeorm"; import define from "@/server/api/define.js"; -import { fetchMeta } from "backend-rs"; +import { fetchMeta, safeForSql } from "backend-rs"; import { Notes } from "@/models/index.js"; import type { Note } from "@/models/entities/note.js"; -import { safeForSql } from "@/misc/safe-for-sql.js"; import { normalizeForSearch } from "@/misc/normalize-for-search.js"; /* diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index e87725e342..f449ea081a 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -1,6 +1,6 @@ import { Brackets } from "typeorm"; import { Notes } from "@/models/index.js"; -import { safeForSql } from "@/misc/safe-for-sql.js"; +import { safeForSql } from "backend-rs"; import { normalizeForSearch } from "@/misc/normalize-for-search.js"; import define from "@/server/api/define.js"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index b159a91944..f28208cba9 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -1,11 +1,11 @@ import { Notes } from "@/models/index.js"; -import { Note } from "@/models/entities/note.js"; +import type { Note } from "@/models/entities/note.js"; import define from "@/server/api/define.js"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; import { generateVisibilityQuery } from "@/server/api/common/generate-visibility-query.js"; import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-query.js"; import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; import type { SelectQueryBuilder } from "typeorm"; export const meta = { diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 517ef615b1..fe15ae18c0 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -2,7 +2,7 @@ import { Brackets } from "typeorm"; import { Followings, Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; import define from "@/server/api/define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["users"], diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index a15a0feb4b..df0701709b 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -2,7 +2,7 @@ import { Brackets } from "typeorm"; import { UserProfiles, Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; import define from "@/server/api/define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; +import { sqlLikeEscape } from "backend-rs"; export const meta = { tags: ["users"],