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