Skip to content

Commit dea22dd

Browse files
committed
Refactor remote support
This moves the logic into a separate file and also implements proper caching.
1 parent 4c6630c commit dea22dd

File tree

5 files changed

+136
-89
lines changed

5 files changed

+136
-89
lines changed

src/Util/util.cpp

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
#include <unistd.h>
77

88
#ifdef Q_OS_UNIX
9-
#include <netdb.h>
109
#include <pwd.h>
11-
#include <unistd.h>
1210
#endif
1311

1412
namespace Util {
@@ -34,79 +32,4 @@ std::string pwd() {
3432
}
3533
return result;
3634
}
37-
38-
bool get_local_domain(std::string &result) {
39-
static std::string cached_result;
40-
if (!cached_result.empty()) {
41-
result = cached_result;
42-
return true;
43-
}
44-
45-
#ifndef Q_OS_UNIX
46-
return false;
47-
#else
48-
char host[HOST_NAME_MAX];
49-
if (gethostname(host, HOST_NAME_MAX)) {
50-
std::cerr << "gethostname failed" << std::endl;
51-
return false;
52-
}
53-
54-
// got the host, try to get the FQDN
55-
struct addrinfo hints, *res;
56-
memset(&hints, 0, sizeof(hints));
57-
hints.ai_family = AF_UNSPEC;
58-
hints.ai_socktype = SOCK_STREAM;
59-
hints.ai_flags = AI_CANONNAME;
60-
61-
int err = getaddrinfo(host, "http", &hints, &res);
62-
if (err) {
63-
std::cerr << "getaddrinfo failed: " << gai_strerror(err) << std::endl;
64-
return false;
65-
}
66-
67-
const auto fqdn = res->ai_canonname;
68-
bool success = true;
69-
70-
if (!strncmp(fqdn, host, HOST_NAME_MAX)) {
71-
std::cerr << "failed to retreive a proper FQDN for " << host << std::endl;
72-
success = false;
73-
} else {
74-
result = fqdn;
75-
76-
// remove possible leading dot
77-
if (result.starts_with('.')) {
78-
result = result.substr(1);
79-
}
80-
81-
cached_result = result;
82-
}
83-
84-
freeaddrinfo(res);
85-
return success;
86-
#endif
87-
}
88-
89-
std::string get_username() {
90-
#ifdef Q_OS_UNIX
91-
return getlogin();
92-
#else
93-
return {};
94-
#endif
95-
}
96-
97-
int get_port() {
98-
const auto env = std::getenv("SSH_CONNECTION");
99-
if (env) {
100-
std::string ssh_connection {env};
101-
const auto n = ssh_connection.rfind(' ');
102-
if (n != std::string::npos) {
103-
try {
104-
return std::stoi(ssh_connection.substr(n + 1));
105-
} catch (std::invalid_argument const &) {
106-
std::cerr << "Failed to parse port number " << ssh_connection << std::endl;
107-
}
108-
}
109-
}
110-
return -1;
111-
}
11235
}

src/Util/util.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,4 @@ namespace Util {
1414

1515
const char *home_dir();
1616
std::string pwd();
17-
bool get_local_domain(std::string &result);
18-
std::string get_username();
19-
int get_port();
2017
}

src/path.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "Util/util.hpp"
66
#include "mimedb.hpp"
7+
#include "remote.hpp"
78
#include "settings.hpp"
89

910
Path::Path(const std::string &p)
@@ -30,15 +31,7 @@ QUrl Path::get_url() const {
3031
auto res = QUrl::fromLocalFile(QString::fromStdString(path.string()));
3132

3233
if (Settings::get()->remote) {
33-
std::string host;
34-
if (Util::get_local_domain(host)) {
35-
res.setScheme("sftp");
36-
res.setUserName(QString::fromStdString(Util::get_username()));
37-
res.setHost(QString::fromStdString(host));
38-
res.setPort(Util::get_port());
39-
} else {
40-
std::cerr << "Failed deducing remote prefix" << std::endl;
41-
}
34+
std::ignore = Remote::get()->rewire_url(res);
4235
}
4336

4437
return res;

src/remote.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#include "remote.hpp"
2+
3+
#include <iostream>
4+
5+
#ifdef Q_OS_UNIX
6+
#include <netdb.h>
7+
#include <unistd.h>
8+
#endif
9+
10+
bool Remote::rewire_url(QUrl &url) {
11+
if (!init_done) {
12+
init();
13+
}
14+
if (!ok) {
15+
return false;
16+
}
17+
18+
url.setScheme("sftp");
19+
url.setUserName(username);
20+
url.setHost(host);
21+
url.setPort(port);
22+
23+
return true;
24+
}
25+
26+
void Remote::init() {
27+
init_done = true;
28+
29+
username = get_username();
30+
if (username.isEmpty()) {
31+
std::cerr << "Could not read username" << std::endl;
32+
return;
33+
}
34+
35+
host = get_local_domain();
36+
if (host.isEmpty()) {
37+
std::cerr << "Could not read host" << std::endl;
38+
return;
39+
}
40+
41+
// not a big deal if this fails, usually it still works without an explicit port
42+
port = get_port();
43+
44+
ok = true;
45+
}
46+
47+
QString Remote::get_local_domain() {
48+
#ifndef Q_OS_UNIX
49+
return {};
50+
#else
51+
char host[HOST_NAME_MAX];
52+
if (gethostname(host, HOST_NAME_MAX)) {
53+
std::cerr << "gethostname failed" << std::endl;
54+
return {};
55+
}
56+
57+
// got the host, try to get the FQDN
58+
struct addrinfo hints, *res;
59+
memset(&hints, 0, sizeof(hints));
60+
hints.ai_family = AF_UNSPEC;
61+
hints.ai_socktype = SOCK_STREAM;
62+
hints.ai_flags = AI_CANONNAME;
63+
64+
int err = getaddrinfo(host, "http", &hints, &res);
65+
if (err) {
66+
std::cerr << "getaddrinfo failed: " << gai_strerror(err) << std::endl;
67+
return {};
68+
}
69+
70+
const auto fqdn = res->ai_canonname;
71+
std::string result;
72+
73+
if (!strncmp(fqdn, host, HOST_NAME_MAX)) {
74+
std::cerr << "failed to retreive a proper FQDN for " << host << std::endl;
75+
} else {
76+
result = fqdn;
77+
78+
// remove possible leading dot
79+
if (result.starts_with('.')) {
80+
result = result.substr(1);
81+
}
82+
}
83+
84+
freeaddrinfo(res);
85+
return QString::fromStdString(result);
86+
#endif
87+
}
88+
89+
QString Remote::get_username() {
90+
#ifdef Q_OS_UNIX
91+
return getlogin();
92+
#else
93+
return {};
94+
#endif
95+
}
96+
97+
int Remote::get_port() {
98+
const auto env = std::getenv("SSH_CONNECTION");
99+
if (env) {
100+
std::string ssh_connection {env};
101+
const auto n = ssh_connection.rfind(' ');
102+
if (n != std::string::npos) {
103+
try {
104+
return std::stoi(ssh_connection.substr(n + 1));
105+
} catch (std::invalid_argument const &) {
106+
std::cerr << "Failed to parse port number " << ssh_connection << std::endl;
107+
}
108+
}
109+
}
110+
return -1;
111+
}

src/remote.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#include <QUrl>
4+
5+
#include "Util/util.hpp"
6+
7+
class Remote {
8+
public:
9+
SINGLETON(Remote)
10+
bool rewire_url(QUrl &url);
11+
private:
12+
void init();
13+
QString get_local_domain();
14+
QString get_username();
15+
int get_port();
16+
17+
bool init_done = false;
18+
bool ok = false;
19+
20+
QString username;
21+
QString host;
22+
int port = -1;
23+
};

0 commit comments

Comments
 (0)