diff --git a/source/system/platform.cpp b/source/system/platform.cpp index d8832c68..83e803a0 100644 --- a/source/system/platform.cpp +++ b/source/system/platform.cpp @@ -18,46 +18,53 @@ #include #include "../detail/mswin/platform_spec.hpp" #elif defined(NANA_POSIX) - #include - #include + #include "split_string.hpp" #include #include #include #include #include #include - #include + #include + #include static void posix_open_url(const char *url_utf8) { + using nana::system::split_string_type; + using nana::system::split_string; + extern char **environ; - const char *home = getenv("HOME"); - std::string cheat(home); - cheat += "/.mozilla"; struct stat exists; + const split_string_type path = getenv("PATH"); - // TODO: generalize this for chromium, opera, waterfox, etc. - // Most desktop environments (KDE, Gnome, Lumina etc.) provide a way to set - // your preferred browser - but there are more desktops than browsers. + //see https://stackoverflow.com/questions/5116473/linux-command-to-open-url-in-default-browser + + std::string full_path; + for (const auto& cur_path : split_string(path, ':')) { + full_path = cur_path; + full_path += "/xdg-open"; + if ( stat(full_path.c_str(), &exists) == 0 && S_ISREG(exists.st_mode)) + break; + else + full_path.clear(); + } + if (full_path.empty()) { + //xdg-open not found sorry :( maybe print a message so users know? + return; + } - // Look for $HOME/.mozilla directory as strong evidence they use firefox. - if ( stat(cheat.c_str(), &exists) == 0 && S_ISDIR(exists.st_mode)) { - const char *path = ""; - static const char *likely[2] = { "/usr/local/bin/firefox", "/usr/bin/firefox"}; - if ( stat(likely[0], &exists) == 0 && S_ISREG(exists.st_mode)) - path = likely[0]; - else if ( stat(likely[1], &exists) == 0 && S_ISREG(exists.st_mode) ) - path = likely[1]; - else return; - pid_t pid = 0; - static const char firefox[] = "firefox"; - char name[sizeof firefox]{}; // argv does not like const-literals so make a copy. - strcpy(name, firefox); - char *argv[3] = {name, const_cast(url_utf8), nullptr}; - posix_spawn(&pid, path, NULL, NULL, argv, environ); + const auto url_utf8_len = std::strlen(url_utf8); + auto string_cpy_buff = std::make_unique(full_path.size() + 1 + url_utf8_len + 1); + char* const url_utf8_cpy = string_cpy_buff.get(); + char* const full_path_cpy = string_cpy_buff.get() + url_utf8_len + 1; + std::strncpy(url_utf8_cpy, url_utf8, url_utf8_len + 1); + std::strncpy(full_path_cpy, full_path.c_str(), full_path.size() + 1); + char *argv[3] = {full_path_cpy, url_utf8_cpy, nullptr}; + //system((full_path + " " + url_utf8).c_str()); + posix_spawn(&pid, full_path_cpy, nullptr, nullptr, argv, environ); } } #endif diff --git a/source/system/split_string.cpp b/source/system/split_string.cpp new file mode 100644 index 00000000..8269db6d --- /dev/null +++ b/source/system/split_string.cpp @@ -0,0 +1,32 @@ +#include "split_string.hpp" +#include +#include +#include + +namespace nana +{ +namespace system { +std::vector split_string (const split_string_type& text, char sep) +{ + std::vector retval; + const auto estimated_size = std::count(text.begin(), text.end(), sep) + 1; + retval.reserve(estimated_size); + + std::size_t sep_pos = 0; + while (sep_pos != text.size()) { + const std::size_t start = sep_pos; + sep_pos = text.find(sep, sep_pos); + sep_pos = (text.npos == sep_pos ? text.size() : sep_pos); + const std::size_t end = sep_pos; + while (sep_pos < text.size() and sep == text[sep_pos]) { + ++sep_pos; + } + + retval.push_back(text.substr(start, end - start)); + } + + return retval; +} + +} +} diff --git a/source/system/split_string.hpp b/source/system/split_string.hpp new file mode 100644 index 00000000..1512ef41 --- /dev/null +++ b/source/system/split_string.hpp @@ -0,0 +1,41 @@ +/* + * The Deploy Implementation + * Nana C++ Library(http://www.nanapro.org) + * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com) + * + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * @file: nana/system/split_string.hpp + * + * What follows is dependent on what defined in nana/config.hpp + */ + +#ifndef NANA_SYSTEM_SPLITSTRING_HPP +#define NANA_SYSTEM_SPLITSTRING_HPP + +#include +#include +#ifdef _nana_std_has_string_view +# include +#else +# include +#endif + +namespace nana +{ +namespace system +{ +#ifdef _nana_std_has_string_view +typedef std::string_view split_string_type; +#else +typedef std::string split_string_type; +#endif + +std::vector split_string (const split_string_type& text, char sep); + +} +} + +#endif