1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef PRINT_IPP_OVER_USB__UTIL_H
17 #define PRINT_IPP_OVER_USB__UTIL_H
18 #ifdef IPPOVERUSB_ENABLE
19 #include <sstream>
20 #include <iostream>
21 #include <iomanip>
22 #include "httplib.h"
23 #include "print_log.h"
24 #include "print_ipp_over_usb_constant.h"
25
26 #define TAG "HttpUSB"
27
28 namespace OHOS::Print {
29 using namespace httplib;
30
31 class PrintIppOverUsbUtil {
32 public:
33 static std::string Uint8ToHexString(const uint8_t *v, const size_t s);
34
35 static std::string IntToHexString(unsigned int v);
36
37 static void TrimString(std::string &s);
38
39 static bool IsStartWithHttpHeader(uint8_t *data, size_t length);
40
41 static bool IsEndWithHttpResponse(uint8_t *data, size_t length);
42
43 static void MakeHeader(size_t startLine, size_t endline, const uint8_t *data, httplib::Response &httpResponse);
44
45 static void DumpRespCode(const uint8_t *data, size_t dataLength, size_t start, size_t dumpLength);
46
47 static int ConstructHttpResponse(const uint8_t *v, const size_t length, httplib::Response &httpResponse);
48 };
49
Uint8ToHexString(const uint8_t * v,const size_t s)50 inline std::string PrintIppOverUsbUtil::Uint8ToHexString(const uint8_t *v, const size_t s)
51 {
52 std::stringstream ss;
53 ss << std::hex << std::setfill('0');
54 for (size_t i = 0; i < s; i++) {
55 ss << std::hex << std::setw(HTTP_COMMON_CONST_VALUE_2) << static_cast<int>(v[i]) << " ";
56 }
57 return ss.str();
58 }
59
IntToHexString(unsigned int v)60 inline std::string PrintIppOverUsbUtil::IntToHexString(unsigned int v)
61 {
62 std::stringstream ss;
63 ss << std::hex << v;
64 std::string temp;
65 ss >> temp;
66 return temp;
67 }
68
TrimString(std::string & s)69 inline void PrintIppOverUsbUtil::TrimString(std::string &s)
70 {
71 if (!s.empty()) {
72 s.erase(0, s.find_first_not_of(" "));
73 s.erase(s.find_last_not_of(" ") + 1);
74 }
75 }
76
IsStartWithHttpHeader(uint8_t * data,size_t length)77 inline bool PrintIppOverUsbUtil::IsStartWithHttpHeader(uint8_t *data, size_t length)
78 { // 是一段http报文的开头
79 if (length > HTTP_COMMON_CONST_VALUE_5 && data[INDEX_0] == HTTP_RESPONSE_H &&
80 data[INDEX_1] == HTTP_RESPONSE_T && data[INDEX_2] == HTTP_RESPONSE_T &&
81 data[INDEX_3] == HTTP_RESPONSE_P &&
82 data[INDEX_4] == HTTP_RESPONSE_VERSION_SPLIT_GANG) {
83 return true;
84 }
85 return false;
86 }
87
IsEndWithHttpResponse(uint8_t * data,size_t length)88 inline bool PrintIppOverUsbUtil::IsEndWithHttpResponse(uint8_t *data, size_t length)
89 { // 是一段http报文的结尾
90 if (data[INDEX_0] == IPP_END_SPLIT_VALUE && length == HTTP_COMMON_CONST_VALUE_1) {
91 return true;
92 } else if (length > HTTP_COMMON_CONST_VALUE_6 && data[INDEX_1] == HTTP_RESPONSE_H &&
93 data[INDEX_2] == HTTP_RESPONSE_T && data[INDEX_3] == HTTP_RESPONSE_T &&
94 data[INDEX_4] == HTTP_RESPONSE_P &&
95 data[INDEX_5] == HTTP_RESPONSE_VERSION_SPLIT_GANG) {
96 return true;
97 } else {
98 return false;
99 }
100 }
101
MakeHeader(size_t startLine,size_t endline,const uint8_t * data,httplib::Response & httpResponse)102 inline void PrintIppOverUsbUtil::MakeHeader(size_t startLine, size_t endline, const uint8_t *data, httplib::Response &httpResponse)
103 {
104 // 提取key和value
105 size_t theSplitIndex = startLine; // ":" 所在的位置
106 while (theSplitIndex < endline && data[theSplitIndex] != CODE_SPLIT_VALUE_COLON) {
107 theSplitIndex++;
108 }
109 std::string keyString;
110 std::string valueString;
111 for (size_t i = startLine; i < theSplitIndex; i++) {
112 keyString += data[i];
113 }
114 for (size_t i = theSplitIndex + 1; i <= endline; i++) {
115 valueString += data[i];
116 }
117 TrimString(keyString);
118 TrimString(valueString);
119 PRINT_HILOGD("keyString :%{public}s, valueString :%{public}s", keyString.c_str(), valueString.c_str());
120 if (HTTP_CONTENT_LENGTH != keyString) {
121 httpResponse.set_header(keyString, valueString);
122 }
123 }
124
DumpRespCode(const uint8_t * data,size_t dataLength,size_t start,size_t dumpLength)125 inline void PrintIppOverUsbUtil::DumpRespCode(const uint8_t *data, size_t dataLength, size_t start, size_t dumpLength)
126 {
127 for (size_t i = start; i < dataLength && i < (start + dumpLength); i++) {
128 PRINT_HILOGE("Resp :%{public}x", data[i]);
129 }
130 }
131
ConstructHttpResponse(const uint8_t * readBuf,const size_t length,httplib::Response & httpResponse)132 inline int PrintIppOverUsbUtil::ConstructHttpResponse(const uint8_t *readBuf, const size_t length, httplib::Response &httpResponse)
133 {
134 PRINT_HILOGD("start construct_http_response length :%{public}lu", length);
135 if (length <= HTTP_COMMON_CONST_VALUE_6) {
136 return INVAILD_VALUE;
137 }
138 const uint8_t *bufTmp = readBuf;
139 size_t index = 0;
140 size_t startline = index;
141 size_t endline = index;
142 while (index < length - INDEX_3) {
143 bool isHeaerEnd = (bufTmp[index] == HTTP_SPLIT_R_CODE && bufTmp[index + INDEX_1] == HTTP_SPLIT_N_CODE &&
144 bufTmp[index + INDEX_2] == HTTP_SPLIT_R_CODE &&
145 bufTmp[index + INDEX_3] == HTTP_SPLIT_N_CODE);
146 if (isHeaerEnd) {
147 break;
148 }
149 bool isLineBegin = (index > INDEX_2 && bufTmp[index - INDEX_2] == HTTP_SPLIT_R_CODE &&
150 bufTmp[index - INDEX_1] == HTTP_SPLIT_N_CODE);
151 if (isLineBegin) { // 识别出一行的第一个字符
152 startline = index;
153 endline = startline;
154 // 识别出一行的行尾
155 while (!(bufTmp[endline + INDEX_1] == HTTP_SPLIT_R_CODE &&
156 bufTmp[endline + INDEX_2] == HTTP_SPLIT_N_CODE)) {
157 endline++;
158 }
159 MakeHeader(startline, endline, readBuf, httpResponse);
160 index++;
161 } else {
162 index++;
163 }
164 }
165 DumpRespCode(bufTmp, length, index + HTTP_COMMON_CONST_VALUE_4, HTTP_COMMON_CONST_VALUE_8);
166 if (index < length - HTTP_COMMON_CONST_VALUE_4) {
167 httpResponse.version = "1.1";
168 httpResponse.status = HTTP_RESPONSE_STATUS_200;
169 httpResponse.reason = "OK";
170 std::string body;
171 index = index + HTTP_COMMON_CONST_VALUE_4;
172 while (index < length) {
173 body += bufTmp[index];
174 index++;
175 }
176 httpResponse.body = body;
177 return 0;
178 } else {
179 return INVAILD_VALUE;
180 }
181 }
182 }
183 #endif // IPPOVERUSB_ENABLE
184 #endif // PRINT_IPP_OVER_USB__UTIL_H