1// Copyright 2014 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "xfa/fxfa/parser/xfa_utils.h" 8 9#include "core/fxcrt/fx_ext.h" 10#include "xfa/fde/xml/fde_xml_imp.h" 11#include "xfa/fxfa/parser/cxfa_document.h" 12#include "xfa/fxfa/parser/cxfa_measurement.h" 13#include "xfa/fxfa/parser/xfa_basic_data.h" 14#include "xfa/fxfa/parser/xfa_localemgr.h" 15#include "xfa/fxfa/parser/xfa_localevalue.h" 16#include "xfa/fxfa/parser/xfa_object.h" 17 18namespace { 19 20const FX_DOUBLE fraction_scales[] = {0.1, 21 0.01, 22 0.001, 23 0.0001, 24 0.00001, 25 0.000001, 26 0.0000001, 27 0.00000001, 28 0.000000001, 29 0.0000000001, 30 0.00000000001, 31 0.000000000001, 32 0.0000000000001, 33 0.00000000000001, 34 0.000000000000001, 35 0.0000000000000001}; 36 37FX_DOUBLE WideStringToDouble(const CFX_WideString& wsStringVal) { 38 CFX_WideString wsValue = wsStringVal; 39 wsValue.TrimLeft(); 40 wsValue.TrimRight(); 41 int64_t nIntegral = 0; 42 uint32_t dwFractional = 0; 43 int32_t nExponent = 0; 44 int32_t cc = 0; 45 bool bNegative = false; 46 bool bExpSign = false; 47 const FX_WCHAR* str = wsValue.c_str(); 48 int32_t len = wsValue.GetLength(); 49 if (str[0] == '+') { 50 cc++; 51 } else if (str[0] == '-') { 52 bNegative = true; 53 cc++; 54 } 55 int32_t nIntegralLen = 0; 56 while (cc < len) { 57 if (str[cc] == '.' || str[cc] == 'E' || str[cc] == 'e' || 58 nIntegralLen > 17) { 59 break; 60 } 61 if (!FXSYS_isDecimalDigit(str[cc])) { 62 return 0; 63 } 64 nIntegral = nIntegral * 10 + str[cc] - '0'; 65 cc++; 66 nIntegralLen++; 67 } 68 nIntegral = bNegative ? -nIntegral : nIntegral; 69 int32_t scale = 0; 70 FX_DOUBLE fraction = 0.0; 71 if (cc < len && str[cc] == '.') { 72 cc++; 73 while (cc < len) { 74 fraction += fraction_scales[scale] * (str[cc] - '0'); 75 scale++; 76 cc++; 77 if (cc == len) { 78 break; 79 } 80 if (scale == sizeof(fraction_scales) / sizeof(FX_DOUBLE) || 81 str[cc] == 'E' || str[cc] == 'e') { 82 break; 83 } 84 if (!FXSYS_isDecimalDigit(str[cc])) { 85 return 0; 86 } 87 } 88 dwFractional = (uint32_t)(fraction * 4294967296.0); 89 } 90 if (cc < len && (str[cc] == 'E' || str[cc] == 'e')) { 91 cc++; 92 if (cc < len) { 93 if (str[cc] == '+') { 94 cc++; 95 } else if (str[cc] == '-') { 96 bExpSign = true; 97 cc++; 98 } 99 } 100 while (cc < len) { 101 if (str[cc] == '.' || !FXSYS_isDecimalDigit(str[cc])) { 102 return 0; 103 } 104 nExponent = nExponent * 10 + str[cc] - '0'; 105 cc++; 106 } 107 nExponent = bExpSign ? -nExponent : nExponent; 108 } 109 FX_DOUBLE dValue = (dwFractional / 4294967296.0); 110 dValue = nIntegral + (nIntegral >= 0 ? dValue : -dValue); 111 if (nExponent != 0) { 112 dValue *= FXSYS_pow(10, (FX_FLOAT)nExponent); 113 } 114 return dValue; 115} 116 117} // namespace 118 119CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData) { 120 CXFA_Node* pNodeValue = 121 pWidgetData->GetNode()->GetChild(0, XFA_Element::Value); 122 if (!pNodeValue) { 123 return CXFA_LocaleValue(); 124 } 125 CXFA_Node* pValueChild = pNodeValue->GetNodeItem(XFA_NODEITEM_FirstChild); 126 if (!pValueChild) { 127 return CXFA_LocaleValue(); 128 } 129 int32_t iVTType = XFA_VT_NULL; 130 switch (pValueChild->GetElementType()) { 131 case XFA_Element::Decimal: 132 iVTType = XFA_VT_DECIMAL; 133 break; 134 case XFA_Element::Float: 135 iVTType = XFA_VT_FLOAT; 136 break; 137 case XFA_Element::Date: 138 iVTType = XFA_VT_DATE; 139 break; 140 case XFA_Element::Time: 141 iVTType = XFA_VT_TIME; 142 break; 143 case XFA_Element::DateTime: 144 iVTType = XFA_VT_DATETIME; 145 break; 146 case XFA_Element::Boolean: 147 iVTType = XFA_VT_BOOLEAN; 148 break; 149 case XFA_Element::Integer: 150 iVTType = XFA_VT_INTEGER; 151 break; 152 case XFA_Element::Text: 153 iVTType = XFA_VT_TEXT; 154 break; 155 default: 156 iVTType = XFA_VT_NULL; 157 break; 158 } 159 return CXFA_LocaleValue(iVTType, pWidgetData->GetRawValue(), 160 pWidgetData->GetNode()->GetDocument()->GetLocalMgr()); 161} 162void XFA_GetPlainTextFromRichText(CFDE_XMLNode* pXMLNode, 163 CFX_WideString& wsPlainText) { 164 if (!pXMLNode) { 165 return; 166 } 167 switch (pXMLNode->GetType()) { 168 case FDE_XMLNODE_Element: { 169 CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); 170 CFX_WideString wsTag; 171 pXMLElement->GetLocalTagName(wsTag); 172 uint32_t uTag = FX_HashCode_GetW(wsTag.AsStringC(), true); 173 if (uTag == 0x0001f714) { 174 wsPlainText += L"\n"; 175 } else if (uTag == 0x00000070) { 176 if (!wsPlainText.IsEmpty()) { 177 wsPlainText += L"\n"; 178 } 179 } else if (uTag == 0xa48ac63) { 180 if (!wsPlainText.IsEmpty() && 181 wsPlainText[wsPlainText.GetLength() - 1] != '\n') { 182 wsPlainText += L"\n"; 183 } 184 } 185 } break; 186 case FDE_XMLNODE_Text: { 187 CFX_WideString wsContent; 188 static_cast<CFDE_XMLText*>(pXMLNode)->GetText(wsContent); 189 wsPlainText += wsContent; 190 } break; 191 case FDE_XMLNODE_CharData: { 192 CFX_WideString wsCharData; 193 static_cast<CFDE_XMLCharData*>(pXMLNode)->GetCharData(wsCharData); 194 wsPlainText += wsCharData; 195 } break; 196 default: 197 break; 198 } 199 for (CFDE_XMLNode* pChildXML = 200 pXMLNode->GetNodeItem(CFDE_XMLNode::FirstChild); 201 pChildXML; 202 pChildXML = pChildXML->GetNodeItem(CFDE_XMLNode::NextSibling)) { 203 XFA_GetPlainTextFromRichText(pChildXML, wsPlainText); 204 } 205} 206 207bool XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode) { 208 bool bRet = false; 209 if (!pFieldNode) 210 return bRet; 211 212 CXFA_Node* pUIChild = pFieldNode->GetChild(0, XFA_Element::Ui); 213 if (pUIChild) { 214 CXFA_Node* pFirstChild = pUIChild->GetNodeItem(XFA_NODEITEM_FirstChild); 215 if (pFirstChild && 216 pFirstChild->GetElementType() == XFA_Element::ChoiceList) { 217 bRet = pFirstChild->GetEnum(XFA_ATTRIBUTE_Open) == 218 XFA_ATTRIBUTEENUM_MultiSelect; 219 } 220 } 221 return bRet; 222} 223 224FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal) { 225 CFX_WideString wsValue = CFX_WideString::FromUTF8(szStringVal); 226 return WideStringToDouble(wsValue); 227} 228 229int32_t XFA_MapRotation(int32_t nRotation) { 230 nRotation = nRotation % 360; 231 nRotation = nRotation < 0 ? nRotation + 360 : nRotation; 232 return nRotation; 233} 234 235const XFA_SCRIPTATTRIBUTEINFO* XFA_GetScriptAttributeByName( 236 XFA_Element eElement, 237 const CFX_WideStringC& wsAttributeName) { 238 if (wsAttributeName.IsEmpty()) 239 return nullptr; 240 241 int32_t iElementIndex = static_cast<int32_t>(eElement); 242 while (iElementIndex != -1) { 243 const XFA_SCRIPTHIERARCHY* scriptIndex = g_XFAScriptIndex + iElementIndex; 244 int32_t icount = scriptIndex->wAttributeCount; 245 if (icount == 0) { 246 iElementIndex = scriptIndex->wParentIndex; 247 continue; 248 } 249 uint32_t uHash = FX_HashCode_GetW(wsAttributeName, false); 250 int32_t iStart = scriptIndex->wAttributeStart, iEnd = iStart + icount - 1; 251 do { 252 int32_t iMid = (iStart + iEnd) / 2; 253 const XFA_SCRIPTATTRIBUTEINFO* pInfo = g_SomAttributeData + iMid; 254 if (uHash == pInfo->uHash) 255 return pInfo; 256 if (uHash < pInfo->uHash) 257 iEnd = iMid - 1; 258 else 259 iStart = iMid + 1; 260 } while (iStart <= iEnd); 261 iElementIndex = scriptIndex->wParentIndex; 262 } 263 return nullptr; 264} 265 266const XFA_NOTSUREATTRIBUTE* XFA_GetNotsureAttribute(XFA_Element eElement, 267 XFA_ATTRIBUTE eAttribute, 268 XFA_ATTRIBUTETYPE eType) { 269 int32_t iStart = 0, iEnd = g_iXFANotsureCount - 1; 270 do { 271 int32_t iMid = (iStart + iEnd) / 2; 272 const XFA_NOTSUREATTRIBUTE* pAttr = g_XFANotsureAttributes + iMid; 273 if (eElement == pAttr->eElement) { 274 if (pAttr->eAttribute == eAttribute) { 275 if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) 276 return pAttr; 277 return nullptr; 278 } 279 int32_t iBefore = iMid - 1; 280 if (iBefore >= 0) { 281 pAttr = g_XFANotsureAttributes + iBefore; 282 while (eElement == pAttr->eElement) { 283 if (pAttr->eAttribute == eAttribute) { 284 if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) 285 return pAttr; 286 return nullptr; 287 } 288 iBefore--; 289 if (iBefore < 0) 290 break; 291 292 pAttr = g_XFANotsureAttributes + iBefore; 293 } 294 } 295 296 int32_t iAfter = iMid + 1; 297 if (iAfter <= g_iXFANotsureCount - 1) { 298 pAttr = g_XFANotsureAttributes + iAfter; 299 while (eElement == pAttr->eElement) { 300 if (pAttr->eAttribute == eAttribute) { 301 if (eType == XFA_ATTRIBUTETYPE_NOTSURE || eType == pAttr->eType) 302 return pAttr; 303 return nullptr; 304 } 305 iAfter++; 306 if (iAfter > g_iXFANotsureCount - 1) 307 break; 308 309 pAttr = g_XFANotsureAttributes + iAfter; 310 } 311 } 312 return nullptr; 313 } 314 315 if (eElement < pAttr->eElement) 316 iEnd = iMid - 1; 317 else 318 iStart = iMid + 1; 319 } while (iStart <= iEnd); 320 return nullptr; 321} 322 323const XFA_PROPERTY* XFA_GetPropertyOfElement(XFA_Element eElement, 324 XFA_Element eProperty, 325 uint32_t dwPacket) { 326 int32_t iCount = 0; 327 const XFA_PROPERTY* pProperties = XFA_GetElementProperties(eElement, iCount); 328 if (!pProperties || iCount < 1) 329 return nullptr; 330 331 auto it = std::find_if(pProperties, pProperties + iCount, 332 [eProperty](const XFA_PROPERTY& prop) { 333 return prop.eName == eProperty; 334 }); 335 if (it == pProperties + iCount) 336 return nullptr; 337 338 const XFA_ELEMENTINFO* pInfo = XFA_GetElementByID(eProperty); 339 ASSERT(pInfo); 340 if (dwPacket != XFA_XDPPACKET_UNKNOWN && !(dwPacket & pInfo->dwPackets)) 341 return nullptr; 342 return it; 343} 344 345const XFA_PROPERTY* XFA_GetElementProperties(XFA_Element eElement, 346 int32_t& iCount) { 347 if (eElement == XFA_Element::Unknown) 348 return nullptr; 349 350 const XFA_ELEMENTHIERARCHY* pElement = 351 g_XFAElementPropertyIndex + static_cast<int32_t>(eElement); 352 iCount = pElement->wCount; 353 return g_XFAElementPropertyData + pElement->wStart; 354} 355 356const uint8_t* XFA_GetElementAttributes(XFA_Element eElement, int32_t& iCount) { 357 if (eElement == XFA_Element::Unknown) 358 return nullptr; 359 360 const XFA_ELEMENTHIERARCHY* pElement = 361 g_XFAElementAttributeIndex + static_cast<int32_t>(eElement); 362 iCount = pElement->wCount; 363 return g_XFAElementAttributeData + pElement->wStart; 364} 365 366const XFA_ELEMENTINFO* XFA_GetElementByID(XFA_Element eName) { 367 return eName != XFA_Element::Unknown 368 ? g_XFAElementData + static_cast<int32_t>(eName) 369 : nullptr; 370} 371 372XFA_Element XFA_GetElementTypeForName(const CFX_WideStringC& wsName) { 373 if (wsName.IsEmpty()) 374 return XFA_Element::Unknown; 375 376 uint32_t uHash = FX_HashCode_GetW(wsName, false); 377 const XFA_ELEMENTINFO* pEnd = g_XFAElementData + g_iXFAElementCount; 378 auto pInfo = std::lower_bound(g_XFAElementData, pEnd, uHash, 379 [](const XFA_ELEMENTINFO& info, uint32_t hash) { 380 return info.uHash < hash; 381 }); 382 if (pInfo < pEnd && pInfo->uHash == uHash) 383 return pInfo->eName; 384 return XFA_Element::Unknown; 385} 386 387CXFA_Measurement XFA_GetAttributeDefaultValue_Measure(XFA_Element eElement, 388 XFA_ATTRIBUTE eAttribute, 389 uint32_t dwPacket) { 390 void* pValue; 391 if (XFA_GetAttributeDefaultValue(pValue, eElement, eAttribute, 392 XFA_ATTRIBUTETYPE_Measure, dwPacket)) { 393 return *(CXFA_Measurement*)pValue; 394 } 395 return CXFA_Measurement(); 396} 397 398bool XFA_GetAttributeDefaultValue(void*& pValue, 399 XFA_Element eElement, 400 XFA_ATTRIBUTE eAttribute, 401 XFA_ATTRIBUTETYPE eType, 402 uint32_t dwPacket) { 403 const XFA_ATTRIBUTEINFO* pInfo = XFA_GetAttributeByID(eAttribute); 404 if (!pInfo) 405 return false; 406 if (dwPacket && (dwPacket & pInfo->dwPackets) == 0) 407 return false; 408 if (pInfo->eType == eType) { 409 pValue = pInfo->pDefValue; 410 return true; 411 } 412 if (pInfo->eType == XFA_ATTRIBUTETYPE_NOTSURE) { 413 const XFA_NOTSUREATTRIBUTE* pAttr = 414 XFA_GetNotsureAttribute(eElement, eAttribute, eType); 415 if (pAttr) { 416 pValue = pAttr->pValue; 417 return true; 418 } 419 } 420 return false; 421} 422 423const XFA_ATTRIBUTEINFO* XFA_GetAttributeByName(const CFX_WideStringC& wsName) { 424 if (wsName.IsEmpty()) 425 return nullptr; 426 427 uint32_t uHash = FX_HashCode_GetW(wsName, false); 428 int32_t iStart = 0; 429 int32_t iEnd = g_iXFAAttributeCount - 1; 430 do { 431 int32_t iMid = (iStart + iEnd) / 2; 432 const XFA_ATTRIBUTEINFO* pInfo = g_XFAAttributeData + iMid; 433 if (uHash == pInfo->uHash) 434 return pInfo; 435 if (uHash < pInfo->uHash) 436 iEnd = iMid - 1; 437 else 438 iStart = iMid + 1; 439 } while (iStart <= iEnd); 440 return nullptr; 441} 442 443const XFA_ATTRIBUTEINFO* XFA_GetAttributeByID(XFA_ATTRIBUTE eName) { 444 return (eName < g_iXFAAttributeCount) ? (g_XFAAttributeData + eName) 445 : nullptr; 446} 447 448const XFA_ATTRIBUTEENUMINFO* XFA_GetAttributeEnumByName( 449 const CFX_WideStringC& wsName) { 450 if (wsName.IsEmpty()) 451 return nullptr; 452 453 uint32_t uHash = FX_HashCode_GetW(wsName, false); 454 int32_t iStart = 0; 455 int32_t iEnd = g_iXFAEnumCount - 1; 456 do { 457 int32_t iMid = (iStart + iEnd) / 2; 458 const XFA_ATTRIBUTEENUMINFO* pInfo = g_XFAEnumData + iMid; 459 if (uHash == pInfo->uHash) 460 return pInfo; 461 if (uHash < pInfo->uHash) 462 iEnd = iMid - 1; 463 else 464 iStart = iMid + 1; 465 } while (iStart <= iEnd); 466 return nullptr; 467} 468 469const XFA_PACKETINFO* XFA_GetPacketByIndex(XFA_PACKET ePacket) { 470 return g_XFAPacketData + ePacket; 471} 472 473const XFA_PACKETINFO* XFA_GetPacketByID(uint32_t dwPacket) { 474 int32_t iStart = 0, iEnd = g_iXFAPacketCount - 1; 475 do { 476 int32_t iMid = (iStart + iEnd) / 2; 477 uint32_t dwFind = (g_XFAPacketData + iMid)->eName; 478 if (dwPacket == dwFind) 479 return g_XFAPacketData + iMid; 480 if (dwPacket < dwFind) 481 iEnd = iMid - 1; 482 else 483 iStart = iMid + 1; 484 } while (iStart <= iEnd); 485 return nullptr; 486} 487