diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f2a337f1..a2a2be86d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ set(SRCS src/common/parsing.c src/common/settings.c src/common/library.c + src/common/networking.c src/detection/plasma.c src/detection/gtk.c src/detection/terminalShell.c @@ -201,6 +202,7 @@ set(SRCS src/modules/battery.c src/modules/locale.c src/modules/localip.c + src/modules/publicip.c src/modules/colors.c ) diff --git a/src/common/init.c b/src/common/init.c index 77a4dfdf7..66bc16625 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -171,6 +171,8 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.localeKey, 0); ffStrbufInitA(&instance->config.localIpKey, 0); ffStrbufInitA(&instance->config.localIpFormat, 0); + ffStrbufInitA(&instance->config.publicIpKey, 0); + ffStrbufInitA(&instance->config.publicIpFormat, 0); ffStrbufInitA(&instance->config.libPCI, 0); ffStrbufInitA(&instance->config.libVulkan, 0); @@ -193,6 +195,8 @@ static void defaultConfig(FFinstance* instance) instance->config.localIpShowIpV4 = true; instance->config.localIpShowIpV6 = false; instance->config.localIpShowLoop = false; + + instance->config.publicIpTimeout = 250; } void ffInitInstance(FFinstance* instance) diff --git a/src/common/networking.c b/src/common/networking.c new file mode 100644 index 000000000..6a27a6ffe --- /dev/null +++ b/src/common/networking.c @@ -0,0 +1,69 @@ +#include "fastfetch.h" + +#include +#include +#include +#include + +void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, FFstrbuf* buffer) +{ + struct addrinfo hints = {0}; + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + struct addrinfo* addr; + + if(getaddrinfo(host, "80", &hints, &addr) != 0) + return; + + int sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if(sock == -1) + { + freeaddrinfo(addr); + return; + } + + if(timeout > 0) + { + struct timeval timev; + timev.tv_sec = 0; + timev.tv_usec = timeout * 1000; //milliseconds to microseconds + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timev, sizeof(timev)); + } + + if(connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) + { + close(sock); + freeaddrinfo(addr); + return; + } + + freeaddrinfo(addr); + + FFstrbuf command; + ffStrbufInitA(&command, 64); + ffStrbufAppendS(&command, "GET "); + ffStrbufAppendS(&command, path); + ffStrbufAppendS(&command, " HTTP/1.1\nHost: "); + ffStrbufAppendS(&command, host); + ffStrbufAppendS(&command, "\r\n\r\n"); + + if(send(sock, command.chars, command.length, 0) == -1) + { + ffStrbufDestroy(&command); + close(sock); + return; + } + + ssize_t received = recv(sock, buffer->chars + buffer->length, ffStrbufGetFree(buffer), 0); + + if(received > 0) + { + buffer->length += (uint32_t) received; + buffer->chars[buffer->length] = '\0'; + } + + ffStrbufDestroy(&command); + close(sock); +} diff --git a/src/data/config.txt b/src/data/config.txt index 750b5fabe..2893f56cf 100644 --- a/src/data/config.txt +++ b/src/data/config.txt @@ -120,6 +120,13 @@ # Default is true. #--color-raw true +# Public IP timeout option: +# Sets the time to wait for the public ip server to respond. +# Must be a positive integer. +# Set to 0 to disable timeout. +# Default is 250. +#--public-ip-timeout 250 + # Key options: # Sets the displayed key of a module # Can be any string. Some of theme take an argument like a format string. See "fastfetch --help format" for help. @@ -148,6 +155,7 @@ #--battery-key Battery {1} #--locale-key Locale #--local-ip-key Local IP ({1}) +#--public-ip-key Public IP # Format options: # Sets the format string for module values. @@ -179,6 +187,7 @@ #--battery-format #--locale-format #--local-ip-format +#--public-ip-format # Library options: # Sets an user specific path to a library to load. diff --git a/src/data/help.txt b/src/data/help.txt index 7553c1039..3f3879a1d 100644 --- a/src/data/help.txt +++ b/src/data/help.txt @@ -61,6 +61,7 @@ Format options: Provide the format string for custom output. Use fastfetch --hel --battery-format --locale-format --local-ip-format + --public-ip-format Key options: Provide a custom key for an output --os-key @@ -88,6 +89,7 @@ Key options: Provide a custom key for an output --battery-key : takes the battery index as format argument --locale-key --local-ip-key : takes the name of this network interface as format argument + --public-ip-key Library options: Set the path of a library to load --lib-PCI @@ -109,6 +111,7 @@ Module specific options: --localip-show-ipv4 : Show ipv4 addresses in local ip module. Default is true --localip-show-ipv6 : Show ipv6 addresses in local ip module. Default is false --localip-show-loop : Show loop back addresses (127.0.0.1) in local ip module. Default is false + --public-ip-timeout: Time in milliseconds to wait for the public ip server to respond. Default is 250. Set to 0 to disable timeout. Parsing is not case sensitive. E.g. "--lib-PCI" is equal to "--Lib-Pci" If a value starts with a ?, it is optional. "true" will be used if not set. diff --git a/src/data/modules.txt b/src/data/modules.txt index b8286f84d..491649288 100644 --- a/src/data/modules.txt +++ b/src/data/modules.txt @@ -12,11 +12,12 @@ Host Icons Kernel Locale -LocalIp +LocalIP Memory OS Packages Processes +PublicIP Resolution Separator Shell diff --git a/src/fastfetch.c b/src/fastfetch.c index 585b0bf10..51dd86a40 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -827,6 +827,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.localIpKey); else if(strcasecmp(key, "--local-ip-format") == 0) optionParseString(key, value, &instance->config.localIpFormat); + else if(strcasecmp(key, "--public-ip-key") == 0) + optionParseString(key, value, &instance->config.publicIpKey); + else if(strcasecmp(key, "--public-ip-format") == 0) + optionParseString(key, value, &instance->config.publicIpFormat); else if(strcasecmp(key, "--lib-PCI") == 0) optionParseString(key, value, &instance->config.libPCI); else if(strcasecmp(key, "--lib-vulkan") == 0) @@ -834,7 +838,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(strcasecmp(key, "--lib-wayland") == 0) optionParseString(key, value, &instance->config.libWayland); else if(strcasecmp(key, "--lib-xcb-randr") == 0) - optionCheckString(key, value, &instance->config.libXcbRandr); + optionParseString(key, value, &instance->config.libXcbRandr); else if(strcasecmp(key, "--lib-xcb") == 0) optionParseString(key, value, &instance->config.libXcb); else if(strcasecmp(key, "--lib-Xrandr") == 0) @@ -861,6 +865,20 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con instance->config.localIpShowIpV6 = optionParseBoolean(value); else if(strcasecmp(key, "--localip-show-loop") == 0) instance->config.localIpShowLoop = optionParseBoolean(value); + else if(strcasecmp(key, "--public-ip-timeout") == 0) + { + if(value == NULL) + { + fprintf(stderr, "Error: usage: %s \n", key); + exit(465); + } + + if(sscanf(value, "%u", &instance->config.publicIpTimeout) != 1) + { + fprintf(stderr, "Error: couldn't parse %s to uint32_t\n", value); + exit(466); + } + } else if(strncasecmp(key, "--color-", 7) == 0 && key[8] != '\0' && key[9] == '\0') // matches "--color-*" { //Map the number to an array index, so that '1' -> 0, '2' -> 1, etc. @@ -1000,6 +1018,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintLocale(instance); else if(strcasecmp(line, "localip") == 0) ffPrintLocalIp(instance); + else if(strcasecmp(line, "publicip") == 0) + ffPrintPublicIp(instance); else if(strcasecmp(line, "colors") == 0) ffPrintColors(instance); else diff --git a/src/fastfetch.h b/src/fastfetch.h index 462f3a39a..89ff6f9dc 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -105,6 +105,8 @@ typedef struct FFconfig FFstrbuf localeKey; FFstrbuf localIpKey; FFstrbuf localIpFormat; + FFstrbuf publicIpKey; + FFstrbuf publicIpFormat; FFstrbuf libPCI; FFstrbuf libVulkan; @@ -128,6 +130,8 @@ typedef struct FFconfig bool localIpShowIpV4; bool localIpShowIpV6; + uint32_t publicIpTimeout; + } FFconfig; typedef struct FFstate @@ -362,6 +366,9 @@ void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]); //common/libraries.c void* ffLibraryLoad(const FFstrbuf* userProvidedName, ...); +//common/networking.c +void ffNetworkingGetHttp(const char* host, const char* path, uint32_t timeout, FFstrbuf* buffer); + //common/logo.c void ffLoadLogoSet(FFinstance* instance, const char* logo); void ffLoadLogo(FFinstance* instance); @@ -456,6 +463,7 @@ void ffPrintDisk(FFinstance* instance); void ffPrintBattery(FFinstance* instance); void ffPrintLocale(FFinstance* instance); void ffPrintLocalIp(FFinstance* instance); +void ffPrintPublicIp(FFinstance* instance); void ffPrintColors(FFinstance* instance); #endif diff --git a/src/flashfetch.c b/src/flashfetch.c index f0d449746..d41e53431 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -44,6 +44,7 @@ int main(int argc, char** argv) ffPrintDisk(&instance); ffPrintBattery(&instance); //ffPrintLocalIp(&instance); + //ffPrintPublicIp(&instance); ffPrintLocale(&instance); ffPrintBreak(&instance); ffPrintColors(&instance); diff --git a/src/modules/localip.c b/src/modules/localip.c index 8e27ad684..26b6828ea 100644 --- a/src/modules/localip.c +++ b/src/modules/localip.c @@ -1,6 +1,6 @@ #include "fastfetch.h" -#define FF_LOCALIP_MODULE_NAME "Local Ip" +#define FF_LOCALIP_MODULE_NAME "Local IP" #define FF_LOCALIP_NUM_FORMAT_ARGS 1 #include diff --git a/src/modules/publicip.c b/src/modules/publicip.c new file mode 100644 index 000000000..f48aa20d9 --- /dev/null +++ b/src/modules/publicip.c @@ -0,0 +1,30 @@ +#include "fastfetch.h" + +#define FF_PUBLICIP_MODULE_NAME "Public IP" +#define FF_PUBLICIP_NUM_FORMAT_ARGS 1 + +void ffPrintPublicIp(FFinstance* instance) +{ + FFstrbuf result; + ffStrbufInitA(&result, 4096); + ffNetworkingGetHttp("ipinfo.io", "/ip", instance->config.publicIpTimeout, &result); + ffStrbufSubstrAfterFirstS(&result, "\r\n\r\n"); + + if(result.length == 0) + { + ffPrintError(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey, &instance->config.publicIpFormat, FF_PUBLICIP_NUM_FORMAT_ARGS, "Failed to connect to an IP detection server"); + return; + } + + if(instance->config.publicIpFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey); + ffStrbufPutTo(&result, stdout); + } + else + { + ffPrintFormatString(instance, FF_PUBLICIP_MODULE_NAME, 0, &instance->config.publicIpKey, &instance->config.publicIpFormat, NULL, FF_PUBLICIP_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &result} + }); + } +} diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index deb62bef3..a0f03f335 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -6,16 +6,6 @@ static char* CHAR_NULL_PTR = ""; -static bool strbufCharsLeft(uint32_t i, const void* strbuf) -{ - return i < ((const FFstrbuf*) strbuf)->length; -} - -static bool strbufCharsLeftS(uint32_t i, const void* str) -{ - return ((const char*) str)[i] != '\0'; -} - void ffStrbufInit(FFstrbuf* strbuf) { ffStrbufInitA(strbuf, FASTFETCH_STRBUF_DEFAULT_ALLOC); @@ -37,7 +27,7 @@ void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* value) ffStrbufInitANS(strbuf, FASTFETCH_STRBUF_DEFAULT_ALLOC, length, value); } -void ffStrbufInitC(FFstrbuf* strbuf, const char c) +void ffStrbufInitC(FFstrbuf* strbuf, char c) { ffStrbufInitAC(strbuf, FASTFETCH_STRBUF_DEFAULT_ALLOC, c); } @@ -65,7 +55,7 @@ void ffStrbufInitANS(FFstrbuf* strbuf, uint32_t allocate, uint32_t length, const ffStrbufAppendNS(strbuf, length, value); } -void ffStrbufInitAC(FFstrbuf* strbuf, uint32_t allocate, const char c) +void ffStrbufInitAC(FFstrbuf* strbuf, uint32_t allocate, char c) { ffStrbufInitA(strbuf, allocate); ffStrbufAppendC(strbuf, c); @@ -164,7 +154,7 @@ void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) ffStrbufAppendNS(strbuf, length, value); } -void ffStrbufSetC(FFstrbuf* strbuf, const char c) +void ffStrbufSetC(FFstrbuf* strbuf, char c) { ffStrbufClear(strbuf); ffStrbufAppendC(strbuf, c); @@ -272,7 +262,7 @@ void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* va strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufAppendC(FFstrbuf* strbuf, const char c) +void ffStrbufAppendC(FFstrbuf* strbuf, char c) { ffStrbufEnsureFree(strbuf, 1); strbuf->chars[strbuf->length++] = c; @@ -436,6 +426,16 @@ uint32_t ffStrbufNextIndexC(const FFstrbuf* strbuf, uint32_t start, char c) return strbuf->length; } +static bool strbufCharsLeft(uint32_t i, const void* strbuf) +{ + return i < ((const FFstrbuf*) strbuf)->length; +} + +static bool strbufCharsLeftS(uint32_t i, const void* str) +{ + return ((const char*) str)[i] != '\0'; +} + static uint32_t strbufNextIndex(const FFstrbuf* strbuf, uint32_t start, const char* chars, const void* container, bool(*charsLeft)(uint32_t, const void*)) { for(uint32_t i = start; i < strbuf->length; i++) @@ -514,12 +514,12 @@ void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index) strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, const char c) +void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c) { ffStrbufSubstrBefore(strbuf, ffStrbufFirstIndexC(strbuf, c)); } -void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, const char c) +void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c) { ffStrbufSubstrBefore(strbuf, ffStrbufLastIndexC(strbuf, c)); } @@ -537,14 +537,21 @@ void ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index) strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, const char c) +void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c) { uint32_t index = ffStrbufFirstIndexC(strbuf, c); if(index < strbuf->length) ffStrbufSubstrAfter(strbuf, index); } -void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, const char c) +void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str) +{ + uint32_t index = ffStrbufFirstIndexS(strbuf, str) + (uint32_t) strlen(str); + if(index < strbuf->length) + ffStrbufSubstrAfter(strbuf, index); +} + +void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c) { uint32_t index = ffStrbufLastIndexC(strbuf, c); if(index < strbuf->length) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 14ad35b8f..f6201780f 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -23,11 +23,11 @@ void ffStrbufInit(FFstrbuf* strbuf); void ffStrbufInitCopy(FFstrbuf* strbuf, const FFstrbuf* src); void ffStrbufInitS(FFstrbuf* strbuf, const char* value); void ffStrbufInitNS(FFstrbuf* strbuf, uint32_t length, const char* value); -void ffStrbufInitC(FFstrbuf* strbuf, const char c); +void ffStrbufInitC(FFstrbuf* strbuf, char c); void ffStrbufInitA(FFstrbuf* strbuf, uint32_t allocate); void ffStrbufInitAS(FFstrbuf* strbuf, uint32_t allocate, const char* value); void ffStrbufInitANS(FFstrbuf* strbuf, uint32_t allocate, uint32_t length, const char* value); -void ffStrbufInitAC(FFstrbuf* strbuf, uint32_t allocate, const char c); +void ffStrbufInitAC(FFstrbuf* strbuf, uint32_t allocate, char c); void ffStrbufInitF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufInitVF(FFstrbuf* strbuf, const char* format, va_list arguments); @@ -41,7 +41,7 @@ void ffStrbufClear(FFstrbuf* strbuf); void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value); void ffStrbufSetS(FFstrbuf* strbuf, const char* value); void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); -void ffStrbufSetC(FFstrbuf* strbuf, const char c); +void ffStrbufSetC(FFstrbuf* strbuf, char c); void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufSetVF(FFstrbuf* strbuf, const char* format, va_list arguments); @@ -51,7 +51,7 @@ void ffStrbufAppendSExcludingC(FFstrbuf* strbuf, const char* value, char exclude void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude); void ffStrbufAppendS(FFstrbuf* strbuf, const char* value); void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value); -void ffStrbufAppendC(FFstrbuf* strbuf, const char c); +void ffStrbufAppendC(FFstrbuf* strbuf, char c); void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); @@ -83,14 +83,16 @@ uint32_t ffStrbufFirstIndex(const FFstrbuf* strbuf, const FFstrbuf* searched); uint32_t ffStrbufFirstIndexS(const FFstrbuf* strbuf, const char* str); uint32_t ffStrbufPreviousIndexC(const FFstrbuf* strbuf, uint32_t start, char c); + uint32_t ffStrbufLastIndexC(const FFstrbuf* strbuf, char c); void ffStrbufSubstrBefore(FFstrbuf* strbuf, uint32_t index); -void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, const char c); -void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, const char c); +void ffStrbufSubstrBeforeFirstC(FFstrbuf* strbuf, char c); +void ffStrbufSubstrBeforeLastC(FFstrbuf* strbuf, char c); void ffStrbufSubstrAfter(FFstrbuf* strbuf, uint32_t index); -void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, const char c); -void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, const char c); +void ffStrbufSubstrAfterFirstC(FFstrbuf* strbuf, char c); +void ffStrbufSubstrAfterFirstS(FFstrbuf* strbuf, const char* str); +void ffStrbufSubstrAfterLastC(FFstrbuf* strbuf, char c); bool ffStrbufStartsWith(const FFstrbuf* strbuf, const FFstrbuf* start); bool ffStrbufStartsWithS(const FFstrbuf* strbuf, const char* start);