| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "xfa/fde/css/fde_csssyntax.h" | 7 #include "xfa/fde/css/fde_csssyntax.h" |
| 8 | 8 |
| 9 #include "xfa/fde/css/fde_cssdatatable.h" | 9 #include "xfa/fde/css/fde_cssdatatable.h" |
| 10 #include "xfa/fgas/crt/fgas_codepage.h" | 10 #include "xfa/fgas/crt/fgas_codepage.h" |
| 11 | 11 |
| 12 #ifdef _cplusplus | 12 #ifdef _cplusplus |
| 13 extern "C" { | 13 extern "C" { |
| 14 #endif | 14 #endif |
| 15 | 15 |
| 16 inline FX_BOOL FDE_IsSelectorStart(FX_WCHAR wch) { | 16 FX_BOOL FDE_IsSelectorStart(FX_WCHAR wch) { |
| 17 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') || | 17 return wch == '.' || wch == '#' || wch == '*' || (wch >= 'a' && wch <= 'z') || |
| 18 (wch >= 'A' && wch <= 'Z'); | 18 (wch >= 'A' && wch <= 'Z'); |
| 19 } | 19 } |
| 20 | 20 |
| 21 #ifdef _cplusplus | 21 #ifdef _cplusplus |
| 22 }; | 22 }; |
| 23 #endif | 23 #endif |
| 24 | 24 |
| 25 CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser() | 25 CFDE_CSSSyntaxParser::CFDE_CSSSyntaxParser() |
| 26 : m_pStream(NULL), | 26 : m_pStream(nullptr), |
| 27 m_iStreamPos(0), | 27 m_iStreamPos(0), |
| 28 m_iPlaneSize(0), | 28 m_iPlaneSize(0), |
| 29 m_iTextDatLen(0), | 29 m_iTextDatLen(0), |
| 30 m_dwCheck((uint32_t)-1), | 30 m_dwCheck((uint32_t)-1), |
| 31 m_eMode(FDE_CSSSYNTAXMODE_RuleSet), | 31 m_eMode(FDE_CSSSYNTAXMODE_RuleSet), |
| 32 m_eStatus(FDE_CSSSYNTAXSTATUS_None) {} | 32 m_eStatus(FDE_CSSSYNTAXSTATUS_None) {} |
| 33 CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() { | 33 CFDE_CSSSyntaxParser::~CFDE_CSSSyntaxParser() { |
| 34 m_TextData.Reset(); | 34 m_TextData.Reset(); |
| 35 m_TextPlane.Reset(); | 35 m_TextPlane.Reset(); |
| 36 } | 36 } |
| 37 FX_BOOL CFDE_CSSSyntaxParser::Init(IFX_Stream* pStream, | 37 FX_BOOL CFDE_CSSSyntaxParser::Init(IFX_Stream* pStream, |
| 38 int32_t iCSSPlaneSize, | 38 int32_t iCSSPlaneSize, |
| 39 int32_t iTextDataSize, | 39 int32_t iTextDataSize, |
| 40 FX_BOOL bOnlyDeclaration) { | 40 FX_BOOL bOnlyDeclaration) { |
| 41 ASSERT(pStream != NULL && iCSSPlaneSize > 0 && iTextDataSize > 0); | 41 ASSERT(pStream && iCSSPlaneSize > 0 && iTextDataSize > 0); |
| 42 Reset(bOnlyDeclaration); | 42 Reset(bOnlyDeclaration); |
| 43 if (!m_TextData.EstimateSize(iTextDataSize)) { | 43 if (!m_TextData.EstimateSize(iTextDataSize)) { |
| 44 return FALSE; | 44 return FALSE; |
| 45 } | 45 } |
| 46 uint8_t bom[4]; | 46 uint8_t bom[4]; |
| 47 m_pStream = pStream; | 47 m_pStream = pStream; |
| 48 m_iStreamPos = m_pStream->GetBOM(bom); | 48 m_iStreamPos = m_pStream->GetBOM(bom); |
| 49 m_iPlaneSize = iCSSPlaneSize; | 49 m_iPlaneSize = iCSSPlaneSize; |
| 50 return TRUE; | 50 return TRUE; |
| 51 } | 51 } |
| 52 FX_BOOL CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer, | 52 FX_BOOL CFDE_CSSSyntaxParser::Init(const FX_WCHAR* pBuffer, |
| 53 int32_t iBufferSize, | 53 int32_t iBufferSize, |
| 54 int32_t iTextDatSize, | 54 int32_t iTextDatSize, |
| 55 FX_BOOL bOnlyDeclaration) { | 55 FX_BOOL bOnlyDeclaration) { |
| 56 ASSERT(pBuffer != NULL && iBufferSize > 0 && iTextDatSize > 0); | 56 ASSERT(pBuffer && iBufferSize > 0 && iTextDatSize > 0); |
| 57 Reset(bOnlyDeclaration); | 57 Reset(bOnlyDeclaration); |
| 58 if (!m_TextData.EstimateSize(iTextDatSize)) { | 58 if (!m_TextData.EstimateSize(iTextDatSize)) { |
| 59 return FALSE; | 59 return FALSE; |
| 60 } | 60 } |
| 61 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize); | 61 return m_TextPlane.AttachBuffer(pBuffer, iBufferSize); |
| 62 } | 62 } |
| 63 void CFDE_CSSSyntaxParser::Reset(FX_BOOL bOnlyDeclaration) { | 63 void CFDE_CSSSyntaxParser::Reset(FX_BOOL bOnlyDeclaration) { |
| 64 m_TextPlane.Reset(); | 64 m_TextPlane.Reset(); |
| 65 m_TextData.Reset(); | 65 m_TextData.Reset(); |
| 66 m_pStream = NULL; | 66 m_pStream = nullptr; |
| 67 m_iStreamPos = 0; | 67 m_iStreamPos = 0; |
| 68 m_iTextDatLen = 0; | 68 m_iTextDatLen = 0; |
| 69 m_dwCheck = (uint32_t)-1; | 69 m_dwCheck = (uint32_t)-1; |
| 70 m_eStatus = FDE_CSSSYNTAXSTATUS_None; | 70 m_eStatus = FDE_CSSSYNTAXSTATUS_None; |
| 71 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName | 71 m_eMode = bOnlyDeclaration ? FDE_CSSSYNTAXMODE_PropertyName |
| 72 : FDE_CSSSYNTAXMODE_RuleSet; | 72 : FDE_CSSSYNTAXMODE_RuleSet; |
| 73 } | 73 } |
| 74 FDE_CSSSYNTAXSTATUS CFDE_CSSSyntaxParser::DoSyntaxParse() { | 74 FDE_CSSSYNTAXSTATUS CFDE_CSSSyntaxParser::DoSyntaxParse() { |
| 75 while (m_eStatus >= FDE_CSSSYNTAXSTATUS_None) { | 75 while (m_eStatus >= FDE_CSSSYNTAXSTATUS_None) { |
| 76 if (m_TextPlane.IsEOF()) { | 76 if (m_TextPlane.IsEOF()) { |
| 77 if (m_pStream == NULL) { | 77 if (!m_pStream) { |
| 78 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && | 78 if (m_eMode == FDE_CSSSYNTAXMODE_PropertyValue && |
| 79 m_TextData.GetLength() > 0) { | 79 m_TextData.GetLength() > 0) { |
| 80 SaveTextData(); | 80 SaveTextData(); |
| 81 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue; | 81 return m_eStatus = FDE_CSSSYNTAXSTATUS_PropertyValue; |
| 82 } | 82 } |
| 83 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS; | 83 return m_eStatus = FDE_CSSSYNTAXSTATUS_EOS; |
| 84 } | 84 } |
| 85 FX_BOOL bEOS; | 85 FX_BOOL bEOS; |
| 86 int32_t iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos, | 86 int32_t iLen = m_TextPlane.LoadFromStream(m_pStream, m_iStreamPos, |
| 87 m_iPlaneSize, bEOS); | 87 m_iPlaneSize, bEOS); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 switch (wch) { | 221 switch (wch) { |
| 222 case ',': | 222 case ',': |
| 223 m_TextPlane.MoveNext(); | 223 m_TextPlane.MoveNext(); |
| 224 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); | 224 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); |
| 225 if (m_iTextDatLen > 0) { | 225 if (m_iTextDatLen > 0) { |
| 226 return FDE_CSSSYNTAXSTATUS_MediaType; | 226 return FDE_CSSSYNTAXSTATUS_MediaType; |
| 227 } | 227 } |
| 228 break; | 228 break; |
| 229 case '{': { | 229 case '{': { |
| 230 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | 230 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); |
| 231 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_MediaRule) { | 231 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_MediaRule) |
| 232 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | 232 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; |
| 233 } | 233 |
| 234 if (m_TextData.GetLength() > 0) { | 234 if (m_TextData.GetLength() > 0) { |
| 235 SaveTextData(); | 235 SaveTextData(); |
| 236 return FDE_CSSSYNTAXSTATUS_MediaType; | 236 return FDE_CSSSYNTAXSTATUS_MediaType; |
| 237 } else { | 237 } else { |
| 238 m_TextPlane.MoveNext(); | 238 m_TextPlane.MoveNext(); |
| 239 *pMode = FDE_CSSSYNTAXMODE_RuleSet; | 239 *pMode = FDE_CSSSYNTAXMODE_RuleSet; |
| 240 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | 240 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); |
| 241 return FDE_CSSSYNTAXSTATUS_DeclOpen; | 241 return FDE_CSSSYNTAXSTATUS_DeclOpen; |
| 242 } | 242 } |
| 243 } break; | 243 } break; |
| 244 case ';': { | 244 case ';': { |
| 245 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | 245 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); |
| 246 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) { | 246 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) |
| 247 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | 247 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; |
| 248 } | 248 |
| 249 if (m_TextData.GetLength() > 0) { | 249 if (m_TextData.GetLength() > 0) { |
| 250 SaveTextData(); | 250 SaveTextData(); |
| 251 if (IsImportEnabled()) { | 251 if (IsImportEnabled()) { |
| 252 return FDE_CSSSYNTAXSTATUS_MediaType; | 252 return FDE_CSSSYNTAXSTATUS_MediaType; |
| 253 } | 253 } |
| 254 } else { | 254 } else { |
| 255 FX_BOOL bEnabled = IsImportEnabled(); | 255 FX_BOOL bEnabled = IsImportEnabled(); |
| 256 m_TextPlane.MoveNext(); | 256 m_TextPlane.MoveNext(); |
| 257 m_ModeStack.Pop(); | 257 m_ModeStack.Pop(); |
| 258 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | 258 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 269 } | 269 } |
| 270 break; | 270 break; |
| 271 } | 271 } |
| 272 default: | 272 default: |
| 273 AppendChar(wch); | 273 AppendChar(wch); |
| 274 break; | 274 break; |
| 275 } | 275 } |
| 276 break; | 276 break; |
| 277 case FDE_CSSSYNTAXMODE_URI: { | 277 case FDE_CSSSYNTAXMODE_URI: { |
| 278 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | 278 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); |
| 279 if (pMode == NULL || *pMode != FDE_CSSSYNTAXMODE_Import) { | 279 if (!pMode || *pMode != FDE_CSSSYNTAXMODE_Import) |
| 280 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; | 280 return m_eStatus = FDE_CSSSYNTAXSTATUS_Error; |
| 281 } | 281 |
| 282 if (wch <= ' ' || wch == ';') { | 282 if (wch <= ' ' || wch == ';') { |
| 283 int32_t iURIStart, iURILength = m_TextData.GetLength(); | 283 int32_t iURIStart, iURILength = m_TextData.GetLength(); |
| 284 if (iURILength > 0 && | 284 if (iURILength > 0 && |
| 285 FDE_ParseCSSURI(m_TextData.GetBuffer(), iURILength, iURIStart, | 285 FDE_ParseCSSURI(m_TextData.GetBuffer(), iURILength, iURIStart, |
| 286 iURILength)) { | 286 iURILength)) { |
| 287 m_TextData.Subtract(iURIStart, iURILength); | 287 m_TextData.Subtract(iURIStart, iURILength); |
| 288 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); | 288 SwitchMode(FDE_CSSSYNTAXMODE_MediaType); |
| 289 if (IsImportEnabled()) { | 289 if (IsImportEnabled()) { |
| 290 return FDE_CSSSYNTAXSTATUS_URI; | 290 return FDE_CSSSYNTAXSTATUS_URI; |
| 291 } else { | 291 } else { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 } | 326 } |
| 327 } | 327 } |
| 328 break; | 328 break; |
| 329 case FDE_CSSSYNTAXMODE_Charset: | 329 case FDE_CSSSYNTAXMODE_Charset: |
| 330 if (wch == ';') { | 330 if (wch == ';') { |
| 331 m_TextPlane.MoveNext(); | 331 m_TextPlane.MoveNext(); |
| 332 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); | 332 SwitchMode(FDE_CSSSYNTAXMODE_RuleSet); |
| 333 if (IsCharsetEnabled()) { | 333 if (IsCharsetEnabled()) { |
| 334 DisableCharset(); | 334 DisableCharset(); |
| 335 if (m_iTextDatLen > 0) { | 335 if (m_iTextDatLen > 0) { |
| 336 if (m_pStream != NULL) { | 336 if (m_pStream) { |
| 337 uint16_t wCodePage = FX_GetCodePageFromStringW( | 337 uint16_t wCodePage = FX_GetCodePageFromStringW( |
| 338 m_TextData.GetBuffer(), m_iTextDatLen); | 338 m_TextData.GetBuffer(), m_iTextDatLen); |
| 339 if (wCodePage < 0xFFFF && | 339 if (wCodePage < 0xFFFF && |
| 340 m_pStream->GetCodePage() != wCodePage) { | 340 m_pStream->GetCodePage() != wCodePage) { |
| 341 m_pStream->SetCodePage(wCodePage); | 341 m_pStream->SetCodePage(wCodePage); |
| 342 } | 342 } |
| 343 } | 343 } |
| 344 return FDE_CSSSYNTAXSTATUS_Charset; | 344 return FDE_CSSSYNTAXSTATUS_Charset; |
| 345 } | 345 } |
| 346 } | 346 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 364 } | 364 } |
| 365 FX_BOOL CFDE_CSSSyntaxParser::IsImportEnabled() const { | 365 FX_BOOL CFDE_CSSSyntaxParser::IsImportEnabled() const { |
| 366 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) { | 366 if ((m_dwCheck & FDE_CSSSYNTAXCHECK_AllowImport) == 0) { |
| 367 return FALSE; | 367 return FALSE; |
| 368 } | 368 } |
| 369 if (m_ModeStack.GetSize() > 1) { | 369 if (m_ModeStack.GetSize() > 1) { |
| 370 return FALSE; | 370 return FALSE; |
| 371 } | 371 } |
| 372 return TRUE; | 372 return TRUE; |
| 373 } | 373 } |
| 374 inline FX_BOOL CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) { | 374 FX_BOOL CFDE_CSSSyntaxParser::AppendChar(FX_WCHAR wch) { |
| 375 m_TextPlane.MoveNext(); | 375 m_TextPlane.MoveNext(); |
| 376 if (m_TextData.GetLength() > 0 || wch > ' ') { | 376 if (m_TextData.GetLength() > 0 || wch > ' ') { |
| 377 m_TextData.AppendChar(wch); | 377 m_TextData.AppendChar(wch); |
| 378 return TRUE; | 378 return TRUE; |
| 379 } | 379 } |
| 380 return FALSE; | 380 return FALSE; |
| 381 } | 381 } |
| 382 inline int32_t CFDE_CSSSyntaxParser::SaveTextData() { | 382 int32_t CFDE_CSSSyntaxParser::SaveTextData() { |
| 383 m_iTextDatLen = m_TextData.TrimEnd(); | 383 m_iTextDatLen = m_TextData.TrimEnd(); |
| 384 m_TextData.Clear(); | 384 m_TextData.Clear(); |
| 385 return m_iTextDatLen; | 385 return m_iTextDatLen; |
| 386 } | 386 } |
| 387 inline void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) { | 387 void CFDE_CSSSyntaxParser::SwitchMode(FDE_CSSSYNTAXMODE eMode) { |
| 388 m_eMode = eMode; | 388 m_eMode = eMode; |
| 389 SaveTextData(); | 389 SaveTextData(); |
| 390 } | 390 } |
| 391 inline int32_t CFDE_CSSSyntaxParser::SwitchToComment() { | 391 int32_t CFDE_CSSSyntaxParser::SwitchToComment() { |
| 392 int32_t iLength = m_TextData.GetLength(); | 392 int32_t iLength = m_TextData.GetLength(); |
| 393 m_ModeStack.Push(m_eMode); | 393 m_ModeStack.Push(m_eMode); |
| 394 SwitchMode(FDE_CSSSYNTAXMODE_Comment); | 394 SwitchMode(FDE_CSSSYNTAXMODE_Comment); |
| 395 return iLength; | 395 return iLength; |
| 396 } | 396 } |
| 397 inline FX_BOOL CFDE_CSSSyntaxParser::RestoreMode() { | 397 FX_BOOL CFDE_CSSSyntaxParser::RestoreMode() { |
| 398 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); | 398 FDE_CSSSYNTAXMODE* pMode = m_ModeStack.GetTopElement(); |
| 399 if (pMode == NULL) { | 399 if (!pMode) |
| 400 return FALSE; | 400 return FALSE; |
| 401 } | 401 |
| 402 SwitchMode(*pMode); | 402 SwitchMode(*pMode); |
| 403 m_ModeStack.Pop(); | 403 m_ModeStack.Pop(); |
| 404 return TRUE; | 404 return TRUE; |
| 405 } | 405 } |
| 406 const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const { | 406 const FX_WCHAR* CFDE_CSSSyntaxParser::GetCurrentString(int32_t& iLength) const { |
| 407 iLength = m_iTextDatLen; | 407 iLength = m_iTextDatLen; |
| 408 return m_TextData.GetBuffer(); | 408 return m_TextData.GetBuffer(); |
| 409 } | 409 } |
| 410 CFDE_CSSTextBuf::CFDE_CSSTextBuf() | 410 CFDE_CSSTextBuf::CFDE_CSSTextBuf() |
| 411 : m_bExtBuf(FALSE), | 411 : m_bExtBuf(FALSE), |
| 412 m_pBuffer(NULL), | 412 m_pBuffer(nullptr), |
| 413 m_iBufLen(0), | 413 m_iBufLen(0), |
| 414 m_iDatLen(0), | 414 m_iDatLen(0), |
| 415 m_iDatPos(0) {} | 415 m_iDatPos(0) {} |
| 416 CFDE_CSSTextBuf::~CFDE_CSSTextBuf() { | 416 CFDE_CSSTextBuf::~CFDE_CSSTextBuf() { |
| 417 Reset(); | 417 Reset(); |
| 418 } | 418 } |
| 419 void CFDE_CSSTextBuf::Reset() { | 419 void CFDE_CSSTextBuf::Reset() { |
| 420 if (!m_bExtBuf) { | 420 if (!m_bExtBuf) { |
| 421 FX_Free(m_pBuffer); | 421 FX_Free(m_pBuffer); |
| 422 m_pBuffer = NULL; | 422 m_pBuffer = nullptr; |
| 423 } | 423 } |
| 424 m_iDatPos = m_iDatLen = m_iBufLen; | 424 m_iDatPos = m_iDatLen = m_iBufLen; |
| 425 } | 425 } |
| 426 FX_BOOL CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, | 426 FX_BOOL CFDE_CSSTextBuf::AttachBuffer(const FX_WCHAR* pBuffer, |
| 427 int32_t iBufLen) { | 427 int32_t iBufLen) { |
| 428 Reset(); | 428 Reset(); |
| 429 m_pBuffer = const_cast<FX_WCHAR*>(pBuffer); | 429 m_pBuffer = const_cast<FX_WCHAR*>(pBuffer); |
| 430 m_iDatLen = m_iBufLen = iBufLen; | 430 m_iDatLen = m_iBufLen = iBufLen; |
| 431 return m_bExtBuf = TRUE; | 431 return m_bExtBuf = TRUE; |
| 432 } | 432 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 if (iLength > m_iDatLen - iStart) { | 475 if (iLength > m_iDatLen - iStart) { |
| 476 iLength = m_iDatLen - iStart; | 476 iLength = m_iDatLen - iStart; |
| 477 } | 477 } |
| 478 if (iLength < 0) { | 478 if (iLength < 0) { |
| 479 iLength = 0; | 479 iLength = 0; |
| 480 } else { | 480 } else { |
| 481 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR)); | 481 FXSYS_memmove(m_pBuffer, m_pBuffer + iStart, iLength * sizeof(FX_WCHAR)); |
| 482 } | 482 } |
| 483 m_iDatLen = iLength; | 483 m_iDatLen = iLength; |
| 484 } | 484 } |
| OLD | NEW |