parse.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. #include "parse.h"
  2. #include "common.h"
  3. #include "encode.h"
  4. namespace NUri {
  5. const TParseFlags TParser::FieldFlags[] =
  6. {
  7. TParseFlags(0 // FieldScheme
  8. | TFeature::FeatureToLower,
  9. 0)
  10. ,
  11. TParseFlags(0 // FieldUsername
  12. | TFeature::FeatureDecodeANY | TFeature::FeaturesDecode | TFeature::FeatureEncodePercent,
  13. 0 | TFeature::FeatureToLower)
  14. ,
  15. TParseFlags(0 // FieldPassword
  16. | TFeature::FeatureDecodeANY | TFeature::FeaturesDecode | TFeature::FeatureEncodePercent,
  17. 0 | TFeature::FeatureToLower)
  18. ,
  19. TParseFlags(0 // FieldHost
  20. | TFeature::FeatureToLower | TFeature::FeatureUpperEncoded | (TFeature::FeaturesMaybeEncode & ~TFeature::FeatureEncodeExtendedDelim),
  21. 0 | TFeature::FeaturesMaybeDecode)
  22. ,
  23. TParseFlags(0 // FieldPort
  24. ,
  25. 0)
  26. ,
  27. TParseFlags(0 // FieldPath
  28. | TFeature::FeaturesEncodePChar | TFeature::FeaturePathOperation,
  29. 0 | TFeature::FeatureToLower | TFeature::FeatureEncodeSpaceAsPlus)
  30. ,
  31. TParseFlags(0 // FieldQuery
  32. | TFeature::FeaturesEncodePChar | TFeature::FeatureEncodeSpaceAsPlus,
  33. 0 | TFeature::FeatureToLower)
  34. ,
  35. TParseFlags(0 // FieldFragment
  36. | TFeature::FeaturesEncodePChar,
  37. 0 | TFeature::FeatureToLower | TFeature::FeatureEncodeSpaceAsPlus)
  38. ,
  39. TParseFlags(0 // FieldHashBang
  40. | TFeature::FeaturesEncodePChar,
  41. 0 | TFeature::FeatureToLower | TFeature::FeatureEncodeSpaceAsPlus)};
  42. namespace NParse {
  43. void TRange::AddRange(const TRange& range, ui64 mask) {
  44. FlagsAllPlaintext |= range.FlagsAllPlaintext;
  45. // update only if flags apply here
  46. mask &= range.FlagsEncodeMasked;
  47. if (0 == mask)
  48. return;
  49. FlagsEncodeMasked |= mask;
  50. if (mask & TFeature::FeaturesMaybeEncode)
  51. Encode += range.Encode;
  52. if (mask & TFeature::FeaturesDecode)
  53. Decode += range.Decode;
  54. }
  55. }
  56. void TParser::copyRequirementsImpl(const char* ptr) {
  57. Y_ASSERT(0 != CurRange.FlagsAllPlaintext);
  58. Y_UNUSED(ptr);
  59. #ifdef DO_PRN
  60. PrintHead(ptr, __FUNCTION__)
  61. << " all=[" << IntToString<16>(CurRange.FlagsAllPlaintext)
  62. << "] enc=[" << IntToString<16>(CurRange.FlagsEncodeMasked)
  63. << " & " << IntToString<16>(Flags.Allow | Flags.Extra) << "]";
  64. PrintTail(CurRange.Beg, ptr);
  65. #endif
  66. for (int i = 0; i < TField::FieldUrlMAX; ++i) {
  67. const TField::EField fld = TField::EField(i);
  68. TSection& section = Sections[fld];
  69. // update only sections in progress
  70. if (nullptr == section.Beg)
  71. continue;
  72. // and overlapping with the range
  73. if (nullptr != section.End && section.End < CurRange.Beg)
  74. continue;
  75. #ifdef DO_PRN
  76. PrintHead(ptr, __FUNCTION__, fld)
  77. << " all=[" << IntToString<16>(CurRange.FlagsAllPlaintext)
  78. << "] enc=[" << IntToString<16>(CurRange.FlagsEncodeMasked)
  79. << " & " << IntToString<16>(GetFieldFlags(fld)) << "]";
  80. PrintTail(section.Beg, ptr);
  81. #endif
  82. section.AddRange(CurRange, GetFieldFlags(fld));
  83. }
  84. CurRange.Reset();
  85. }
  86. void TParser::PctEndImpl(const char* ptr) {
  87. #ifdef DO_PRN
  88. PrintHead(PctBegin, __FUNCTION__);
  89. PrintTail(PctBegin, ptr);
  90. #else
  91. Y_UNUSED(ptr);
  92. #endif
  93. setRequirement(PctBegin, TEncoder::GetFlags('%').FeatFlags);
  94. PctBegin = nullptr;
  95. }
  96. void TParser::HexSet(const char* ptr) {
  97. Y_ASSERT(nullptr != PctBegin);
  98. #ifdef DO_PRN
  99. PrintHead(ptr, __FUNCTION__);
  100. PrintTail(PctBegin, ptr + 1);
  101. #endif
  102. PctBegin = nullptr;
  103. const unsigned char ch = HexValue;
  104. ui64 flags = TEncoder::GetFlags('%').FeatFlags | TEncoder::GetFlags(ch).FeatFlags;
  105. setRequirementExcept(ptr, flags, TFeature::FeaturesMaybeEncode);
  106. }
  107. TState::EParsed TParser::ParseImpl() {
  108. #ifdef DO_PRN
  109. PrintHead(UriStr.data(), "[Parsing]") << "URL";
  110. PrintTail(UriStr);
  111. #endif
  112. const bool ok = doParse(UriStr.data(), UriStr.length());
  113. #ifdef DO_PRN
  114. Cdbg << (ok ? "[Parsed]" : "[Failed]");
  115. for (int idx = 0; idx < TField::FieldUrlMAX; ++idx) {
  116. const TSection& section = Sections[idx];
  117. if (section.IsSet())
  118. Cdbg << ' ' << TField::EField(idx) << "=[" << section.Get() << ']';
  119. }
  120. Cdbg << Endl;
  121. #endif
  122. if (!ok) {
  123. if (!(Flags & TFeature::FeatureTryToFix) || !Sections[TField::FieldFrag].Beg)
  124. return TState::ParsedBadFormat;
  125. //Here: error was in fragment, just ignore it
  126. ResetSection(TField::FieldFrag);
  127. }
  128. if ((Flags & TFeature::FeatureDenyNetworkPath) && IsNetPath())
  129. return TState::ParsedBadFormat;
  130. const TSection& scheme = Sections[TField::FieldScheme];
  131. Scheme = scheme.IsSet() ? TSchemeInfo::GetKind(scheme.Get()) : TScheme::SchemeEmpty;
  132. const TSchemeInfo& schemeInfo = TSchemeInfo::Get(Scheme);
  133. if (IsRootless()) {
  134. // opaque case happens
  135. if (schemeInfo.FldReq & TField::FlagHost)
  136. return TState::ParsedBadFormat;
  137. if (TScheme::SchemeEmpty == Scheme)
  138. return TState::ParsedBadScheme;
  139. if (Flags & TFeature::FeatureAllowRootless)
  140. return TState::ParsedOK;
  141. if (!(Flags & TFeature::FeatureSchemeFlexible))
  142. return TState::ParsedBadScheme;
  143. return TState::ParsedRootless;
  144. }
  145. checkSectionCollision(TField::FieldUser, TField::FieldHost);
  146. checkSectionCollision(TField::FieldPass, TField::FieldPort);
  147. if (0 == (Flags & TFeature::FeatureAuthSupported))
  148. if (Sections[TField::FieldUser].IsSet() || Sections[TField::FieldPass].IsSet())
  149. return TState::ParsedBadAuth;
  150. TSection& host = Sections[TField::FieldHost];
  151. if (host.IsSet())
  152. for (; host.End != host.Beg && '.' == host.End[-1];)
  153. --host.End;
  154. if (scheme.IsSet()) {
  155. ui64 wantCareFlags = 0;
  156. switch (Scheme) {
  157. case TScheme::SchemeHTTP:
  158. break;
  159. case TScheme::SchemeEmpty:
  160. Scheme = TScheme::SchemeUnknown;
  161. [[fallthrough]];
  162. case TScheme::SchemeUnknown:
  163. wantCareFlags =
  164. TFeature::FeatureSchemeFlexible | TFeature::FeatureNoRelPath;
  165. break;
  166. default:
  167. wantCareFlags =
  168. TFeature::FeatureSchemeFlexible | TFeature::FeatureSchemeKnown;
  169. break;
  170. }
  171. if (0 != wantCareFlags && 0 == (Flags & wantCareFlags))
  172. return TState::ParsedBadScheme;
  173. if ((schemeInfo.FldReq & TField::FlagHost) || (Flags & TFeature::FeatureRemoteOnly))
  174. if (!host.IsSet() || 0 == host.Len())
  175. return TState::ParsedBadFormat;
  176. }
  177. return TState::ParsedOK;
  178. }
  179. }