(c++) sftp Connect & read xml
c, c++, vs, sftp, ftp, CkSFtp, xml, pugi, pugixml
(c++) sftp Connect & read xml
sftp xml ,
- 최초 작성일: 2023년 6월 29일 (목)
(CksFtp )
###
- sftp 접속: CksFtp
- xml 접속: pugixml
CksFtp 라이브러리는 상용(유료) 소프트웨어로 제공된다. 한 달 사용 후에는 해당 라이브러리를 계속 이용하려면 유료 라이선스를 구매해야 한다. 이 점을 참고하시기 바란다.
필자도 제대로 확인 안 하고 사용했다가 갑자기 작동이 안되어서 당황했다.
그래서, 아래에 무료인 libssh 라이브러리를 사용한 버전을 구현했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
bool CExampleDlg::connectToServer(CkSFtp& sftp, const char* hostname, int port) {
if (sftp.Connect(hostname, port) != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
if (sftp.AuthenticatePw("root", "fa") != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
if (sftp.InitializeSftp() != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
return true;
}
bool CExampleDlg::downloadRemoteFile(CkSFtp& sftp, const char* remoteFilePath, const char* localFilePath) {
const char* handle = sftp.openFile(remoteFilePath, "readOnly", "openExisting");
if (sftp.get_LastMethodSuccess() != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
if (sftp.DownloadFile(handle, localFilePath) != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
if (sftp.CloseHandle(handle) != true) {
std::cerr << sftp.lastErrorText() << "\n";
return false;
}
return true;
}
pugi::xml_document CExampleDlg::loadAndParseXml(const char* xmlFilePath) {
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(xmlFilePath);
if (!result) {
std::cerr << "Parsing failed with description: " << result.description() << "\n";
return {};
}
return doc;
}
std::string CExampleDlg::findAndValidateNode(pugi::xml_document& doc, const char* nodeName) {
pugi::xml_node node = doc.child("Root").child(nodeName);
if (!node) {
std::cerr << nodeName << " node not found." << std::endl;
return "";
}
std::string nodeValue = node.text().get();
try {
if (std::stoi(nodeValue) >= 100 || std::stoi(nodeValue) <= -100) {
std::cerr << "Invalid value for " << nodeName << ": " << nodeValue << std::endl;
return "";
}
}
catch (std::exception& e) {
std::cerr << "Exception caught trying to convert " << nodeName << " to integer: " << e.what() << std::endl;
return "";
}
return nodeValue;
}
std::pair<std::string, std::string> CExampleDlg::connectSftp() {
CkSFtp sftp;
if (!connectToServer(sftp, "192.168.8.1", 22)) {
return { "", "" };
}
if (!downloadRemoteFile(sftp, "/home/pi/test/test.xml", "./xml/test.xml")) {
return { "", "" };
}
pugi::xml_document doc = loadAndParseXml("./xml/test.xml");
if (!doc) {
return { "", "" };
}
std::string setPhaseCalW = findAndValidateNode(doc, "SetPhaseCalW");
std::string setPhaseCalH = findAndValidateNode(doc, "SetPhaseCalH");
if (setPhaseCalW.empty() || setPhaseCalH.empty()) {
return { "", "" };
}
std::cout << "setPhaseCalW: " << setPhaseCalW << std::endl;
std::cout << "setPhaseCalH: " << setPhaseCalH << std::endl;
return { setPhaseCalW, setPhaseCalH };
}
2 (libssh2 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
bool CExampleDlg::connectToServer(LIBSSH2_SESSION*& session, const char* hostname, int port, const char* username, const char* password) {
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
// Use inet_pton instead of inet_addr
if (inet_pton(AF_INET, hostname, &sin.sin_addr) <= 0) {
std::cerr << "Invalid address format\n";
return false;
}
if (connect(sock, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) {
std::cerr << "Failed to connect to " << hostname << "\n";
return false;
}
session = libssh2_session_init();
if (libssh2_session_handshake(session, sock)) {
std::cerr << "Failed to establish SSH session\n";
return false;
}
if (libssh2_userauth_password(session, username, password)) {
std::cerr << "Authentication failed\n";
return false;
}
return true;
}
bool CExampleDlg::downloadRemoteFile(LIBSSH2_SESSION*& session, const char* remoteFilePath, const char* localFilePath)
{
LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session);
if (!sftp_session) {
std::cerr << "Failed to initialize SFTP session\n";
return false;
}
unsigned int filename_len = static_cast<unsigned int>(strlen(remoteFilePath));
LIBSSH2_SFTP_HANDLE* sftp_handle = libssh2_sftp_open_ex(sftp_session, remoteFilePath, filename_len, LIBSSH2_FXF_READ, 0, LIBSSH2_SFTP_OPENFILE);
if (!sftp_handle) {
std::cerr << "Failed to open file with SFTP\n";
libssh2_sftp_shutdown(sftp_session);
return false;
}
FILE* localFile;
errno_t err = fopen_s(&localFile, localFilePath, "wb");
if (err != 0 || !localFile) {
std::cerr << "Failed to open local file\n";
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
return false;
}
char buffer[1024];
while (true) {
ssize_t amount = libssh2_sftp_read(sftp_handle, buffer, static_cast<unsigned int>(sizeof(buffer))); // explicit cast to unsigned int
if (amount > 0) {
size_t result = fwrite(buffer, 1, static_cast<size_t>(amount), localFile);
if (result != static_cast<size_t>(amount)) {
std::cerr << "Failed to write to local file\n";
fclose(localFile);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
return false;
}
}
else if (amount == 0) {
break; // EOF reached
}
else {
std::cerr << "Failed to read from remote file\n";
fclose(localFile);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
return false;
}
}
fclose(localFile);
libssh2_sftp_close(sftp_handle);
libssh2_sftp_shutdown(sftp_session);
return true;
}
pugi::xml_document CExampleDlg::loadAndParseXml(const char* xmlFilePath) {
pugi::xml_document doc;
pugi::xml_parse_result result = doc.load_file(xmlFilePath);
if (!result) {
std::cerr << "Parsing failed with description: " << result.description() << "\n";
return {};
}
return doc;
}
std::string CExampleDlg::findAndValidateNode(pugi::xml_document& doc, const char* nodeName) {
pugi::xml_node node = doc.child("Root").child(nodeName);
if (!node) {
std::cerr << nodeName << " node not found." << std::endl;
return "";
}
std::string nodeValue = node.text().get();
try {
if (std::stoi(nodeValue) >= 100 || std::stoi(nodeValue) <= -100) {
std::cerr << "Invalid value for " << nodeName << ": " << nodeValue << std::endl;
return "";
}
}
catch (std::exception& e) {
std::cerr << "Exception caught trying to convert " << nodeName << " to integer: " << e.what() << std::endl;
return "";
}
return nodeValue;
}
std::pair<std::string, std::string> CExampleDlg::connectSftp() {
LIBSSH2_SESSION* session;
if (!connectToServer(session, "192.168.8.1", 22, "root", "fa")) {
return { "", "" };
}
if (!downloadRemoteFile(session, "/home/pi/test/test.xml", "./xml/test.xml")) {
libssh2_session_disconnect(session, "Finished session");
libssh2_session_free(session);
return { "", "" };
}
pugi::xml_document doc = loadAndParseXml("./xml/test.xml");
if (!doc) {
libssh2_session_disconnect(session, "Finished session");
libssh2_session_free(session);
return { "", "" };
}
std::string setPhaseCalW = findAndValidateNode(doc, "SetPhaseCalW");
std::string setPhaseCalH = findAndValidateNode(doc, "SetPhaseCalH");
if (setPhaseCalW.empty() || setPhaseCalH.empty()) {
libssh2_session_disconnect(session, "Finished session");
libssh2_session_free(session);
return { "", "" };
}
std::cout << "setPhaseCalW: " << setPhaseCalW << std::endl;
std::cout << "setPhaseCalH: " << setPhaseCalH << std::endl;
libssh2_session_disconnect(session, "Finished session");
libssh2_session_free(session);
return { setPhaseCalW, setPhaseCalH };
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.