mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 10:19:08 +00:00
Add byte length checks to poll question and options during create
Co-authored-by: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com>
This commit is contained in:
@@ -1534,6 +1534,14 @@
|
|||||||
"messageformat": "Poll requires at least 2 options",
|
"messageformat": "Poll requires at least 2 options",
|
||||||
"description": "Error message shown when poll has fewer than 2 non-empty options"
|
"description": "Error message shown when poll has fewer than 2 non-empty options"
|
||||||
},
|
},
|
||||||
|
"icu:PollCreateModal__Error--QuestionTooLong": {
|
||||||
|
"messageformat": "Question is too long",
|
||||||
|
"description": "Error message shown when poll question string exceeds the byte limit"
|
||||||
|
},
|
||||||
|
"icu:PollCreateModal__Error--OptionTooLong": {
|
||||||
|
"messageformat": "Option is too long",
|
||||||
|
"description": "Error message shown when poll option string exceeds the byte limit"
|
||||||
|
},
|
||||||
"icu:deleteConversation": {
|
"icu:deleteConversation": {
|
||||||
"messageformat": "Delete",
|
"messageformat": "Delete",
|
||||||
"description": "Menu item for deleting a conversation (including messages), title case."
|
"description": "Menu item for deleting a conversation (including messages), title case."
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
POLL_OPTIONS_MAX_COUNT,
|
POLL_OPTIONS_MAX_COUNT,
|
||||||
} from '../types/Polls.dom.js';
|
} from '../types/Polls.dom.js';
|
||||||
import { count as countGraphemes } from '../util/grapheme.std.js';
|
import { count as countGraphemes } from '../util/grapheme.std.js';
|
||||||
|
import { MAX_MESSAGE_BODY_BYTE_LENGTH } from '../util/longAttachment.std.js';
|
||||||
|
|
||||||
type PollOption = {
|
type PollOption = {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -212,20 +213,34 @@ export function PollCreateModal({
|
|||||||
hasQuestionError: boolean;
|
hasQuestionError: boolean;
|
||||||
hasOptionsError: boolean;
|
hasOptionsError: boolean;
|
||||||
} => {
|
} => {
|
||||||
const errors: Array<string> = [];
|
const questionErrors: Array<string> = [];
|
||||||
const hasQuestionError = !question.trim();
|
const optionErrors: Array<string> = [];
|
||||||
const nonEmptyOptions = options.filter(opt => opt.value.trim());
|
|
||||||
const hasOptionsError = nonEmptyOptions.length < POLL_OPTIONS_MIN_COUNT;
|
|
||||||
|
|
||||||
if (hasQuestionError) {
|
const questionValue = question.trim();
|
||||||
errors.push(i18n('icu:PollCreateModal__Error--RequiresQuestion'));
|
if (!questionValue) {
|
||||||
|
questionErrors.push(i18n('icu:PollCreateModal__Error--RequiresQuestion'));
|
||||||
|
}
|
||||||
|
if (Buffer.byteLength(questionValue) > MAX_MESSAGE_BODY_BYTE_LENGTH) {
|
||||||
|
questionErrors.push(i18n('icu:PollCreateModal__Error--QuestionTooLong'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasOptionsError) {
|
const optionValues = options.map(opt => opt.value.trim());
|
||||||
errors.push(i18n('icu:PollCreateModal__Error--RequiresTwoOptions'));
|
const nonEmptyOptions = optionValues.filter(value => value);
|
||||||
|
if (nonEmptyOptions.length < POLL_OPTIONS_MIN_COUNT) {
|
||||||
|
optionErrors.push(i18n('icu:PollCreateModal__Error--RequiresTwoOptions'));
|
||||||
|
}
|
||||||
|
const optionOverByteLength = optionValues.find(
|
||||||
|
value => Buffer.byteLength(value) > MAX_MESSAGE_BODY_BYTE_LENGTH
|
||||||
|
);
|
||||||
|
if (optionOverByteLength) {
|
||||||
|
optionErrors.push(i18n('icu:PollCreateModal__Error--OptionTooLong'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { errors, hasQuestionError, hasOptionsError };
|
return {
|
||||||
|
errors: questionErrors.concat(optionErrors),
|
||||||
|
hasQuestionError: questionErrors.length > 0,
|
||||||
|
hasOptionsError: optionErrors.length > 0,
|
||||||
|
};
|
||||||
}, [question, options, i18n]);
|
}, [question, options, i18n]);
|
||||||
|
|
||||||
const handleSend = useCallback(() => {
|
const handleSend = useCallback(() => {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import * as RemoteConfig from '../RemoteConfig.dom.js';
|
|||||||
import { isAlpha, isBeta, isProduction } from '../util/version.std.js';
|
import { isAlpha, isBeta, isProduction } from '../util/version.std.js';
|
||||||
import type { SendStateByConversationId } from '../messages/MessageSendState.std.js';
|
import type { SendStateByConversationId } from '../messages/MessageSendState.std.js';
|
||||||
import { aciSchema } from './ServiceId.std.js';
|
import { aciSchema } from './ServiceId.std.js';
|
||||||
|
import { MAX_MESSAGE_BODY_BYTE_LENGTH } from '../util/longAttachment.std.js';
|
||||||
|
|
||||||
export const POLL_QUESTION_MAX_LENGTH = 100;
|
export const POLL_QUESTION_MAX_LENGTH = 100;
|
||||||
export const POLL_OPTIONS_MIN_COUNT = 2;
|
export const POLL_OPTIONS_MIN_COUNT = 2;
|
||||||
@@ -28,7 +29,13 @@ export const PollCreateSchema = z
|
|||||||
.min(1)
|
.min(1)
|
||||||
.refine(value => hasAtMostGraphemes(value, POLL_QUESTION_MAX_LENGTH), {
|
.refine(value => hasAtMostGraphemes(value, POLL_QUESTION_MAX_LENGTH), {
|
||||||
message: `question must contain at most ${POLL_QUESTION_MAX_LENGTH} characters`,
|
message: `question must contain at most ${POLL_QUESTION_MAX_LENGTH} characters`,
|
||||||
}),
|
})
|
||||||
|
.refine(
|
||||||
|
value => Buffer.byteLength(value) <= MAX_MESSAGE_BODY_BYTE_LENGTH,
|
||||||
|
{
|
||||||
|
message: `question must contain at most ${MAX_MESSAGE_BODY_BYTE_LENGTH} bytes`,
|
||||||
|
}
|
||||||
|
),
|
||||||
options: z
|
options: z
|
||||||
.array(
|
.array(
|
||||||
z
|
z
|
||||||
@@ -40,6 +47,12 @@ export const PollCreateSchema = z
|
|||||||
message: `option must contain at most ${POLL_QUESTION_MAX_LENGTH} characters`,
|
message: `option must contain at most ${POLL_QUESTION_MAX_LENGTH} characters`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.refine(
|
||||||
|
value => Buffer.byteLength(value) <= MAX_MESSAGE_BODY_BYTE_LENGTH,
|
||||||
|
{
|
||||||
|
message: `option must contain at most ${MAX_MESSAGE_BODY_BYTE_LENGTH} bytes`,
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.min(POLL_OPTIONS_MIN_COUNT)
|
.min(POLL_OPTIONS_MIN_COUNT)
|
||||||
.max(POLL_OPTIONS_MAX_COUNT)
|
.max(POLL_OPTIONS_MAX_COUNT)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { unicodeSlice } from './unicodeSlice.std.js';
|
import { unicodeSlice } from './unicodeSlice.std.js';
|
||||||
|
|
||||||
const KIBIBYTE = 1024;
|
const KIBIBYTE = 1024;
|
||||||
const MAX_MESSAGE_BODY_BYTE_LENGTH = 2 * KIBIBYTE;
|
export const MAX_MESSAGE_BODY_BYTE_LENGTH = 2 * KIBIBYTE;
|
||||||
|
|
||||||
export const MAX_BODY_ATTACHMENT_BYTE_LENGTH = 64 * KIBIBYTE;
|
export const MAX_BODY_ATTACHMENT_BYTE_LENGTH = 64 * KIBIBYTE;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user