@@ -61,6 +61,9 @@ private function newEntry(): void
6161 */
6262 private function saveEntry (): void
6363 {
64+ if ($ this ->translations ->getTranslations ()[$ this ->translation ->getId ()] ?? null ) {
65+ throw new Exception ("Duplicated entry at byte {$ this ->position }" );
66+ }
6467 $ this ->translations ->add ($ this ->translation );
6568 }
6669
@@ -328,6 +331,7 @@ private function readContext(): bool
328331 private function readOriginal (): void
329332 {
330333 $ data = $ this ->readIdentifier ('msgid ' , true );
334+ $ this ->checkNewLine ($ data , 'msgid ' );
331335 $ this ->translation = $ this ->translation ->withOriginal ($ data );
332336 }
333337
@@ -339,6 +343,7 @@ private function readPlural(): bool
339343 if (($ data = $ this ->readIdentifier ('msgid_plural ' )) === null ) {
340344 return false ;
341345 }
346+ $ this ->checkNewLine ($ data , 'msgid_plural ' );
342347 $ this ->translation ->setPlural ($ data );
343348
344349 return true ;
@@ -355,6 +360,10 @@ private function readTranslation(): void
355360 }
356361 $ this ->readWhiteSpace ();
357362 $ data = $ this ->readQuotedString ();
363+ // The header might be surrounded by newlines
364+ if ($ this ->translation ->getOriginal () !== '' ) {
365+ $ this ->checkNewLine ($ data , 'msgstr ' );
366+ }
358367 $ this ->translation ->translate ($ data );
359368 }
360369
@@ -392,6 +401,7 @@ private function readPluralTranslation(bool $throwIfNotFound = false): bool
392401 $ this ->readWhiteSpace ();
393402 $ data = $ this ->readQuotedString ();
394403 $ translations [] = $ data ;
404+ $ this ->checkNewLine ($ data , 'msgstr ' );
395405 $ this ->translation ->translate (array_shift ($ translations ));
396406 $ this ->translation ->translatePlural (...$ translations );
397407
@@ -452,4 +462,15 @@ private function readHeaders(?string $string): array
452462
453463 return $ headers ;
454464 }
465+
466+ /**
467+ * Ensures the data doesn't start nor end with a newline
468+ */
469+ private function checkNewLine (string $ data , string $ context ): void
470+ {
471+ if (($ first = substr ($ data , 0 , 1 )) === "\n" || $ first === "\r"
472+ || ($ last = substr ($ data , -1 )) === "\n" || $ last === "\n" ) {
473+ throw new Exception ("$ context cannot start nor end with a newline at byte {$ this ->position }" );
474+ }
475+ }
455476}
0 commit comments