mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2025-12-20 02:08:57 +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",
|
||||
"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": {
|
||||
"messageformat": "Delete",
|
||||
"description": "Menu item for deleting a conversation (including messages), title case."
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
POLL_OPTIONS_MAX_COUNT,
|
||||
} from '../types/Polls.dom.js';
|
||||
import { count as countGraphemes } from '../util/grapheme.std.js';
|
||||
import { MAX_MESSAGE_BODY_BYTE_LENGTH } from '../util/longAttachment.std.js';
|
||||
|
||||
type PollOption = {
|
||||
id: string;
|
||||
@@ -212,20 +213,34 @@ export function PollCreateModal({
|
||||
hasQuestionError: boolean;
|
||||
hasOptionsError: boolean;
|
||||
} => {
|
||||
const errors: Array<string> = [];
|
||||
const hasQuestionError = !question.trim();
|
||||
const nonEmptyOptions = options.filter(opt => opt.value.trim());
|
||||
const hasOptionsError = nonEmptyOptions.length < POLL_OPTIONS_MIN_COUNT;
|
||||
const questionErrors: Array<string> = [];
|
||||
const optionErrors: Array<string> = [];
|
||||
|
||||
if (hasQuestionError) {
|
||||
errors.push(i18n('icu:PollCreateModal__Error--RequiresQuestion'));
|
||||
const questionValue = question.trim();
|
||||
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) {
|
||||
errors.push(i18n('icu:PollCreateModal__Error--RequiresTwoOptions'));
|
||||
const optionValues = options.map(opt => opt.value.trim());
|
||||
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]);
|
||||
|
||||
const handleSend = useCallback(() => {
|
||||
|
||||
@@ -12,6 +12,7 @@ import * as RemoteConfig from '../RemoteConfig.dom.js';
|
||||
import { isAlpha, isBeta, isProduction } from '../util/version.std.js';
|
||||
import type { SendStateByConversationId } from '../messages/MessageSendState.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_OPTIONS_MIN_COUNT = 2;
|
||||
@@ -28,7 +29,13 @@ export const PollCreateSchema = z
|
||||
.min(1)
|
||||
.refine(value => hasAtMostGraphemes(value, POLL_QUESTION_MAX_LENGTH), {
|
||||
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
|
||||
.array(
|
||||
z
|
||||
@@ -40,6 +47,12 @@ export const PollCreateSchema = z
|
||||
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)
|
||||
.max(POLL_OPTIONS_MAX_COUNT)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { unicodeSlice } from './unicodeSlice.std.js';
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user