Compare commits

..

No commits in common. "master" and "v1.0" have entirely different histories.
master ... v1.0

41 changed files with 636 additions and 2557 deletions

68
.gitignore vendored
View File

@ -1 +1,67 @@
cmake-build-debug/
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

View File

@ -1,68 +0,0 @@
stages:
- build
- post
# Unix Build
build:
stage: build
image: luki42/dynuiprefresher_build:latest
script:
- cmake -S . -B build -D WinBuild=OFF -D GUI=OFF
- cd build
- make dynuiprefresher
artifacts:
paths:
- build/bin/
build_package:
stage: post
image: luki42/dynuiprefresher_build:latest
script:
- cmake -S . -B build -D WinBuild=OFF -D GUI=OFF
- cd build
- make package
artifacts:
paths:
- build/packages/
needs:
- build
test:
stage: post
image: luki42/dynuiprefresher_build:latest
script:
- cmake -S . -B build -D WinBuild=OFF -D GUI=OFF
- cd build
- make build-test
artifacts:
reports:
junit: build/*.xml
needs:
- build
# Windows Build
build_win64:
stage: build
image: luki42/dynuiprefresher_build:windows
script:
- cmake -S . -B build -D WinBuild=ON
- cd build
- make dynuiprefresher
artifacts:
paths:
- build/bin/
build_package_win64:
stage: post
image: luki42/dynuiprefresher_build:windows
script:
- cmake -S . -B build -D WinBuild=ON
- cd build
- make package
artifacts:
paths:
- build/packages/
needs:
- build_win64

2
.idea/iprefresher.iml generated Normal file
View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/iprefresher.iml" filepath="$PROJECT_DIR$/.idea/iprefresher.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

371
.idea/workspace.xml generated Normal file
View File

@ -0,0 +1,371 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BookmarkManager">
<bookmark url="file://$PROJECT_DIR$/src/Logger.cpp" line="41" mnemonic="2" />
</component>
<component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
<generated>
<config projectName="iprefresher" targetName="iprefresher" />
</generated>
</component>
<component name="CMakeSettings">
<configurations>
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
</configurations>
</component>
<component name="ChangeListManager">
<list default="true" id="59c80f39-2468-4db0-9afd-14b8acdbffed" name="Default Changelist" comment="deleted cmake files">
<change afterPath="$PROJECT_DIR$/src/Logger.cpp" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/Logger.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMakeLists.txt" beforeDir="false" afterPath="$PROJECT_DIR$/CMakeLists.txt" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/API.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/src/API.cpp" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/src/main.cpp" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/cmake-build-debug/" />
<ignored path="$PROJECT_DIR$/CMakeFiles/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="CMakeBuildProfile:Debug" />
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/API.h">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="14" column="124" selection-start-line="14" selection-start-column="124" selection-end-line="14" selection-end-column="124" />
<folding>
<element signature="e#95#112#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/API.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="281">
<caret line="44" column="17" selection-start-line="44" selection-start-column="17" selection-end-line="44" selection-end-column="17" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Hashmap.h">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/main.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="29" column="41" lean-forward="true" selection-start-line="29" selection-start-column="41" selection-end-line="29" selection-end-column="41" />
<folding>
<element signature="e#0#19#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/cmake-build-debug/CMakeCache.txt">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Logger.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="555">
<caret line="37" column="38" lean-forward="true" selection-start-line="37" selection-start-column="38" selection-end-line="37" selection-end-column="38" />
<folding>
<element signature="e#40#58#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/cmake-build-debug/ip.txt">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/cmake-build-debug/dynurefresher.log">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/Logger.h">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="38" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="38" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="424">
<caret line="38" column="23" selection-start-line="38" selection-start-column="23" selection-end-line="38" selection-end-column="23" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/API.h" />
<option value="$PROJECT_DIR$/main.cpp" />
<option value="$PROJECT_DIR$/API.cpp" />
<option value="$PROJECT_DIR$/CMakeLists.txt" />
<option value="$PROJECT_DIR$/.gitignore" />
<option value="$PROJECT_DIR$/src/API.cpp" />
<option value="$PROJECT_DIR$/src/Logger.h" />
<option value="$PROJECT_DIR$/src/main.cpp" />
<option value="$PROJECT_DIR$/src/Logger.cpp" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="1020" />
<option name="y" value="236" />
<option name="width" value="1914" />
<option name="height" value="1051" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="iprefresher" type="b2602c69:ProjectViewProjectNode" />
<item name="DynuIPRefresher" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="iprefresher" type="b2602c69:ProjectViewProjectNode" />
<item name="DynuIPRefresher" type="462c0819:PsiDirectoryNode" />
<item name="cmake-build-debug" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="iprefresher" type="b2602c69:ProjectViewProjectNode" />
<item name="DynuIPRefresher" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/src" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager">
<configuration name="iprefresher" type="CMakeRunConfiguration" factoryName="Application" PASS_PARENT_ENVS_2="true" PROJECT_NAME="iprefresher" TARGET_NAME="iprefresher" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="iprefresher" RUN_TARGET_NAME="iprefresher">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="59c80f39-2468-4db0-9afd-14b8acdbffed" name="Default Changelist" comment="" />
<created>1556620677257</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1556620677257</updated>
<workItem from="1556620678990" duration="5234000" />
<workItem from="1556646880233" duration="656000" />
<workItem from="1556710548728" duration="6200000" />
<workItem from="1557047487321" duration="761000" />
<workItem from="1557061811880" duration="5098000" />
</task>
<task id="LOCAL-00001" summary="edited api class and made it to work">
<created>1557063528491</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1557063528491</updated>
</task>
<task id="LOCAL-00002" summary="edited api class and made it to work">
<created>1557063846200</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1557063846200</updated>
</task>
<task id="LOCAL-00003" summary="deleted cmake files">
<created>1557063931807</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1557063931807</updated>
</task>
<option name="localTasksCounter" value="4" />
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="17949000" />
</component>
<component name="ToolWindowManager">
<frame x="1919" y="0" width="1922" height="1081" extended-state="6" />
<editor active="true" />
<layout>
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.26040554" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="Favorites" order="2" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info active="true" anchor="bottom" id="Run" order="2" visible="true" weight="0.31875" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="bottom" id="Database Changes" order="7" />
<window_info anchor="bottom" id="Messages" order="8" weight="0.32708332" />
<window_info anchor="bottom" id="Terminal" order="9" />
<window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
<window_info anchor="bottom" id="Version Control" order="11" />
<window_info anchor="bottom" id="CMake" order="12" weight="0.32834226" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
<window_info anchor="right" id="Database" order="3" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="edited api class and made it to work" />
<MESSAGE value="deleted cmake files" />
<option name="LAST_COMMIT_MESSAGE" value="deleted cmake files" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/test.cpp" />
<entry file="file://$PROJECT_DIR$/test.h" />
<entry file="file://$PROJECT_DIR$/cmake_install.cmake" />
<entry file="file://$PROJECT_DIR$/iprefresher.cbp" />
<entry file="file://$PROJECT_DIR$/CMakeLists.txt">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="135">
<caret line="9" column="19" selection-start-line="9" selection-start-column="19" selection-end-line="9" selection-end-column="19" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/API.h">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="210">
<caret line="14" column="124" selection-start-line="14" selection-start-column="124" selection-end-line="14" selection-end-column="124" />
<folding>
<element signature="e#95#112#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Hashmap.h">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/.gitignore">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="424">
<caret line="38" column="23" selection-start-line="38" selection-start-column="23" selection-end-line="38" selection-end-column="23" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/API.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="281">
<caret line="44" column="17" selection-start-line="44" selection-start-column="17" selection-end-line="44" selection-end-column="17" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/cmake-build-debug/out.myfile">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="15">
<caret line="1" column="6" selection-start-line="1" selection-start-column="6" selection-end-line="1" selection-end-column="6" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/Logger.h">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="150">
<caret line="10" column="38" selection-start-line="10" selection-start-column="22" selection-end-line="10" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/cmake-build-debug/CMakeCache.txt">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/cmake-build-debug/ip.txt">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/cmake-build-debug/dynurefresher.log">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/src/Logger.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="555">
<caret line="37" column="38" lean-forward="true" selection-start-line="37" selection-start-column="38" selection-end-line="37" selection-end-column="38" />
<folding>
<element signature="e#40#58#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main.cpp">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="289">
<caret line="29" column="41" lean-forward="true" selection-start-line="29" selection-start-column="41" selection-end-line="29" selection-end-column="41" />
<folding>
<element signature="e#0#19#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

View File

@ -1,509 +1,16 @@
# @author Lukas Heiligenbrunner cmake_minimum_required(VERSION 3.14)
# main CMake file project(iprefresher)
#
# Build lib dependencies:
## libcurl (with sources)
## libconfig (with sources)
#
# for documenation build doxygen needs to be installed.
# for test build gtest needs to be installed.
cmake_minimum_required(VERSION 3.13) set(CMAKE_CXX_STANDARD 17)
project(dynuiprefresher DESCRIPTION "Dynu ip refresher" LANGUAGES)
SET(PROJECT_VERSION 1.3.4)
# CONFIGURATION find_package(CURL REQUIRED)
SET(CMAKE_BUILD_TYPE Release) # manually SET build type (Release / Debug) include_directories(${CURL_INCLUDE_DIR})
SET(LIB_METHOD STATIC) #SHARED / STATIC
option(BUILD_DOC "Build documentation" ON) # additional dependency for Doxygen
option(PACKAGING "Allow Packaging to <exe>, <deb> or <rpm>" ON) # additional dependencies for RPMbuild,dpkg or NSIS
option(TESTS "Build Tests" ON) # additional dependencies for GTEST - to build tests
option(GUI "Build GUI elements" ON) # additional dependencies to QT libraries needed
option(WinBuild "cross compile for Windows Platform" ON)
# helper variables set(SOURCE src/main.cpp src/API.h src/API.cpp src/Hashmap.h src/Logger.cpp src/Logger.h)
SET(CMAKE_CXX_STANDARD 17)
string(TIMESTAMP TIMESTAMP_NOW "%d.%m.%Y")
SET(Application_Name "dynuiprefresher")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) add_executable(iprefresher ${SOURCE})
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# setup winbuild compilers
if (${WinBuild})
message(STATUS "setup Mingw Toolchain for cross compile.")
set(LIBSUFFIX .dll)
set(SUFFIX .exe)
set(CMAKE_SYSTEM_NAME WindowsStore)
set(CMAKE_SYSTEM_VERSION 10.0)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32) # x64 build toolchain
#set(TOOLCHAIN_PREFIX i686-w64-mingw32)
# cross compilers to use for C and C++ target_link_libraries(iprefresher ${CURL_LIBRARIES})
set(CMAKE_C_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-g++)
set(CMAKE_RC_COMPILER /usr/bin/${TOOLCHAIN_PREFIX}-windres)
# target environment on the build host system
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CSS_STANDARD_LIBRARIES}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
# currently libs are dynamically linked eg. dlls have to be copied to same folder
# todo link dynamically.
# maybe so: set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++ -static")
# or set(CMAKE_CXX_STANDARD_LIBRARIES -lcurl -lpthread -static-libgcc -static-libstdc++ -lcrypto -lssl -lws2_32 -static -DCURL_STATICLIB)
# or add_definitions(-DCURL_STATICLIB)
# windows config path is in %appdata% folder of user
set(CONFIG_PATH "std::string(std::getenv(\"USERPROFILE\")) + \"\\\\AppData\\\\Roaming\\\\DynuIPrefresher\\\\\"")
# temp file is also stored in appdata folder
set(TempFilePath "std::string(std::getenv(\"USERPROFILE\")) + \"\\\\AppData\\\\Roaming\\\\DynuIPrefresher\\\\\"")
else ()
message(STATUS "using nativ gcc toolchain.")
set(LIBSUFFIX .so)
set(SUFFIX "")
# set linux config path
set(CONFIG_PATH "\"/etc/\"")
# set path of temp file
set(TempFilePath "\"/var/tmp/\"")
endif ()
# test compiler settings and enable languages here
message("")
message(STATUS "Testing the C++ compiler!")
enable_language(CXX)
message("")
message(STATUS "Testing the C compiler!")
enable_language(C)
# config libs
message("")
message(STATUS "Config of Libraries")
# libcurl
if (${WinBuild})
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
# configure libcurl
FIND_PATH(CURL_INCLUDE_DIRS curl/curl.h /usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/include/) # search for libconfig include headers
FIND_LIBRARY(CURL_LIBRARIES NAMES libcurl.dll.a HINTS /usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/lib) # search for actual lib
message(STATUS "Using CURL include dir(s): ${CURL_INCLUDE_DIRS}")
message(STATUS "Using CURL lib(s): ${CURL_LIBRARIES}")
message(STATUS "")
include_directories(${CURL_INCLUDE_DIRS})
# configure libconfig
FIND_PATH(LIBCONFIG++_INCLUDE_DIRS libconfig.h++ /usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/include/) # search for libconfig include headers
FIND_LIBRARY(LIBCONFIG++_LIBRARIES NAMES libconfig++.dll.a HINTS /usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/lib) # search for actual lib
message(STATUS "Using LIBCONFIG++ include dir(s): ${LIBCONFIG++_INCLUDE_DIRS}")
message(STATUS "Using LIBCONFIG++ lib(s): ${LIBCONFIG++_LIBRARIES}")
if (${GUI})
set(CMAKE_PREFIX_PATH "/usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/lib/cmake")
endif ()
include_directories(${LIBCONFIG++_INCLUDE_DIRS})
else ()
find_package(CURL REQUIRED)
if (CURL_INCLUDE_DIRS AND CURL_LIBRARIES)
message(STATUS "Found CURL version: ${CURL_VERSION_STRING}")
message(STATUS "Using CURL include dir(s): ${CURL_INCLUDE_DIRS}")
message(STATUS "Using CURL lib(s): ${CURL_LIBRARIES}")
else ()
message(FATAL_ERROR "Could not find CURL")
endif ()
include_directories(${CURL_INCLUDE_DIR})
message("")
# libconfig
FIND_PATH(LIBCONFIG++_INCLUDE_DIRS
NAMES libconfig.h++
PATHS /usr/include /usr/local/include) # search for libconfig include headers
FIND_LIBRARY(LIBCONFIG++_LIBRARIES
NAMES config++
PATHS /usr/lib /usr/local/lib) # search for actual lib
if (LIBCONFIG++_INCLUDE_DIRS AND LIBCONFIG++_LIBRARIES)
message(STATUS "Fount libconfig!")
message(STATUS "Using libconfig include dir(s): ${LIBCONFIG++_INCLUDE_DIRS}")
message(STATUS "Using libconfig lib(s): ${LIBCONFIG++_LIBRARIES}")
else ()
message(FATAL_ERROR "Could not find LIBCONFIG")
endif ()
include_directories(${LIBCONFIG_INCLUDE_DIRS})
endif ()
if (${GUI})
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5PrintSupport REQUIRED)
find_package(Qt5Sql REQUIRED)
endif ()
include_directories(inc)
message("")
#read sample config
FILE(READ ${CMAKE_SOURCE_DIR}/config/dynuiprefresher.cfg SAMPLECONFIG)
#add StaticData header
FILE(WRITE ${CMAKE_SOURCE_DIR}/inc/StaticData.h
"/**
* StaticData header to store Version, Config dir and a Sample config
* Do not edit this file manually, it is generated by the cmake script!
*
* @author Lukas Heiligenbrunner
* @date ${TIMESTAMP_NOW}
*/
#pragma once
#include <string>
namespace StaticData {
const std::string VERSION = \"${PROJECT_VERSION}\";
const std::string TempFilePath = ${TempFilePath};
const std::string ConfigDir = ${CONFIG_PATH};
const std::string ConfName = \"${Application_Name}.cfg\";
const std::string SAMPLECONFIG = R\"(${SAMPLECONFIG})\";
}"
)
add_library(api ${LIB_METHOD}
src/api/API.cpp
src/api/TelegramAPI.cpp
src/api/DynuAPI.cpp
src/api/IPAPI.cpp)
add_library(libdynuiprefresher ${LIB_METHOD}
src/IPRefresher.cpp
src/Config.cpp
src/IpHelper.cpp
src/FileLogger.cpp
src/Logger.cpp
)
add_executable(${Application_Name} src/main.cpp)
# LINK generated LIBS #
target_link_libraries(${Application_Name} libdynuiprefresher api ${CURL_LIBRARIES} ${LIBCONFIG++_LIBRARIES})
if (${GUI})
set(QT5_LIBRARIES Qt5::Widgets Qt5::PrintSupport Qt5::Sql)
set(UI_SOURCES
src/gui/mainwindow.ui
)
#
# Generate necessary headers from .ui files. (qmake lets `uic` do this job.)
# hint from [Cross-platform Qt5 project using cmake](http://stackoverflow.com/questions/21174586/cross-platform-qt5-project-using-cmake)
#
qt5_wrap_ui(UI_GENERATED_HEADERS ${UI_SOURCES})
add_executable(${Application_Name}-gui
src/maingui.cpp
src/gui/MainWindow.cpp
inc/gui/MainWindow.h
${UI_GENERATED_HEADERS})
if (${WinBuild})
# hide console window when starting ui on windows
set_target_properties(${Application_Name}-gui PROPERTIES LINK_FLAGS "-mwindows")
endif ()
# LINK generated LIBS #
target_link_libraries(${Application_Name}-gui -lpthread libdynuiprefresher api ${CURL_LIBRARIES} ${LIBCONFIG++_LIBRARIES} ${QT5_LIBRARIES})
endif ()
# setting install targets
IF (NOT ${WinBuild})
# INSTALL to Linux SYSTEM #
# install binaries
install(
TARGETS ${Application_Name}
DESTINATION usr/bin
COMPONENT ${Application_Name})
# install systemd service and enable it
install(
FILES service/${Application_Name}.service
DESTINATION lib/systemd/system
COMPONENT ${Application_Name})
if (${GUI})
# install binaries
install(
TARGETS ${Application_Name}-gui
DESTINATION usr/bin
COMPONENT ${Application_Name}gui)
endif ()
ELSE ()
# INSTALL to Windows SYSTEM #
# install binary to current folder
set_target_properties(${Application_Name} PROPERTIES SUFFIX ".exe")
install(
TARGETS ${Application_Name}
DESTINATION .
COMPONENT ${Application_Name})
# install .dll dependencies
# todo check if files exist...
SET(LIBBINARYPATH "/usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/bin")
install(FILES /usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/bin/libcurl-4.dll
${LIBBINARYPATH}/libssh2-1.dll
${LIBBINARYPATH}/libstdc++-6.dll
${LIBBINARYPATH}/libgcc_s_seh-1.dll
${LIBBINARYPATH}/libcrypto-1_1-x64.dll
${LIBBINARYPATH}/libssl-1_1-x64.dll
${LIBBINARYPATH}/libwinpthread-1.dll
${LIBBINARYPATH}/zlib1.dll
${LIBBINARYPATH}/libidn2-0.dll
${LIBBINARYPATH}/libconfig++-11.dll
DESTINATION .
COMPONENT ${Application_Name})
if (${GUI})
# install binaries
set_target_properties(${Application_Name}-gui PROPERTIES SUFFIX ".exe")
install(
TARGETS ${Application_Name}-gui
DESTINATION .
COMPONENT ${Application_Name}gui)
# install .dll dependencies
install(FILES
${LIBBINARYPATH}/Qt5Widgets.dll
${LIBBINARYPATH}/Qt5Core.dll
${LIBBINARYPATH}/Qt5Gui.dll
${LIBBINARYPATH}/iconv.dll
${LIBBINARYPATH}/libpcre2-16-0.dll
${LIBBINARYPATH}/libpng16-16.dll
${LIBBINARYPATH}/libharfbuzz-0.dll
${LIBBINARYPATH}/libglib-2.0-0.dll
${LIBBINARYPATH}/libintl-8.dll
${LIBBINARYPATH}/libpcre-1.dll
${LIBBINARYPATH}/libbz2-1.dll
${LIBBINARYPATH}/libfreetype-6.dll
DESTINATION .
COMPONENT ${Application_Name}gui)
install(FILES
/usr/${TOOLCHAIN_PREFIX}/sys-root/mingw/lib/qt5/plugins/platforms/qwindows.dll
DESTINATION ./platforms
COMPONENT ${Application_Name}gui)
endif ()
ENDIF ()
if (${PACKAGING})
# General Packaging options:
message(STATUS "config of Package build")
set(CPACK_PACKAGE_NAME "DynuIpRefresher")
SET(CPACK_PACKAGE_DESCRIPTION "IPrefresher to refresh Dynu ip address and notify user via Telegram")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "IPrefresher to refresh Dynu ip address and notify user via Telegram")
SET(CPACK_PACKAGE_VENDOR "Lukas Heilgienbrunner")
SET(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}")
SET(CPACK_PACKAGE_CONTACT "Lukas Heiligenbrunner <lukas.heiligenbrunner@gmail.com>")
SET(CMAKE_INSTALL_PREFIX "/")
IF (NOT ${WinBuild})
# generate post script for checking if configuration already exists
FILE(WRITE ${CMAKE_SOURCE_DIR}/postinst
"#!/bin/bash
# Post installation script for linux packages
# do not edit this file manually, it is generated by the cmake script
if [ ! -f ${CONFIG_PATH} ]; then
cat > ${CONFIG_PATH} <<- EOM
${SAMPLECONFIG}EOM
fi
systemctl enable ${Application_Name}.service
systemctl restart ${Application_Name}.service")
SET(CPACK_DEB_COMPONENT_INSTALL 1)
SET(CPACK_OUTPUT_FILE_PREFIX packages)
SET(CPACK_PACKAGING_INSTALL_PREFIX "/") # no prefix for package structure
FIND_PROGRAM(RPMBUILD_EXECUTABLE rpmbuild)
FIND_PROGRAM(DEB_EXECUTABLE dpkg)
SET(CPACK_GENERATOR "TGZ;TBZ2")
#check if rpm build is possible
if (NOT ${RPMBUILD_EXECUTABLE} STREQUAL "RPMBUILD_EXECUTABLE-NOTFOUND")
message(STATUS "found rpm build executeable --> able to build rpm")
SET(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
SET(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/postinst")
SET(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
"/lib/systemd/system"
"/lib/systemd"
"/lib"
"/usr/local/bin"
"/usr/local") # --> not override existing folders
# dependency management tested with fedora!
set(CPACK_RPM_PACKAGE_REQUIRES "libcurl,libconfig")
if (${GUI})
# append rpm GUI dependencies (qt5)
set(CPACK_RPM_PACKAGE_REQUIRES "${CPACK_RPM_PACKAGE_REQUIRES},qt5-qtbase")
endif ()
else (NOT ${RPMBUILD_EXECUTABLE} STREQUAL "RPMBUILD_EXECUTABLE-NOTFOUND")
message(STATUS "not found rpm build tools --> not building rpm")
endif (NOT ${RPMBUILD_EXECUTABLE} STREQUAL "RPMBUILD_EXECUTABLE-NOTFOUND")
#check if deb build is possible
if (NOT ${DEB_EXECUTABLE} STREQUAL "DEB_EXECUTABLE-NOTFOUND")
message(STATUS "found deb build tools --> able to build deb")
SET(CPACK_GENERATOR "${CPACK_GENERATOR};DEB") # add deb generator
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/postinst") # set post inst file
# dependency management tested with fedora!
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libcurl4,libconfig++9v5") # add debian dependencies
if (${GUI})
# append debian GUI dependencies (qt5)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},qt5-default")
endif ()
else (NOT ${DEB_EXECUTABLE} STREQUAL "DEB_EXECUTABLE-NOTFOUND")
message(STATUS "not found deb build tools --> not building deb")
endif (NOT ${DEB_EXECUTABLE} STREQUAL "DEB_EXECUTABLE-NOTFOUND")
SET(CPACK_CMAKE_GENERATOR "Unix Makefiles")
SET(CPACK_SOURCE_GENERATOR "TGZ;TBZ2")
SET(CPACK_PACKAGE_SECTION "games")
ELSE ()
# Pack a NSIS intaller
set(CPACK_GENERATOR NSIS)
message(STATUS "Using NSIS Package build.")
set(CPACK_NSIS_EXECUTABLES_DIRECTORY "DynuIpRefresher")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "DynuIpRefresher")
SET(CPACK_NSIS_MODIFY_PATH ON)
set(CPACK_NSIS_MENU_LINKS
"${Application_Name}.exe" "DynuIpRefresher Console"
"${Application_Name}-gui.exe" "DynuIpRefresher GUI")
# varnames need uppercase strings
string(TOUPPER ${Application_Name} APPLICATION_NAME_UPPER)
# Define components and their display names
set (CPACK_COMPONENTS_ALL ${Application_Name} ${Application_Name}gui)
set (CPACK_COMPONENT_${APPLICATION_NAME_UPPER}_DISPLAY_NAME "Dynu IP Refresher Console")
set (CPACK_COMPONENT_${APPLICATION_NAME_UPPER}GUI_DISPLAY_NAME "Dynu IP Refresher GUI")
# Human readable component descriptions
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}_DESCRIPTION "An extremely useful application that makes use of MyLib")
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}GUI_DESCRIPTION "Static libraries used to build programs with MyLib")
# Define dependencies between components
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}GUI_DEPENDS ${Application_Name})
# Define groups
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}_GROUP "Runtime")
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}GUI_GROUP "Development")
set(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION "All of the tools you'll ever need to develop software")
# Define NSIS installation types
set(CPACK_ALL_INSTALL_TYPES Full Developer)
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}_INSTALL_TYPES Developer Full)
set(CPACK_COMPONENT_${APPLICATION_NAME_UPPER}GUI_INSTALL_TYPES Full)
ENDIF ()
INCLUDE(CPack)
add_custom_target(build-packages
"${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target package
DEPENDS ${Application_Name}
COMMENT "Packing ${Application_Name}")
message("")
ENDIF ()
# check if Doxygen is installed
if (BUILD_DOC)
message(STATUS "config of DOxygen build")
find_package(Doxygen)
if (DOXYGEN_FOUND)
# SET input and output files
SET(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/docs/Doxyfile.in)
SET(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc_doxygen ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
message(STATUS "Successfully configured doxygen")
else (DOXYGEN_FOUND)
message(STATUS "Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
message("")
endif (BUILD_DOC)
# Test Cases
if (TESTS)
# include(GoogleTest)
message(STATUS "Configuring GTEST")
find_package(GTest)
if (GTEST_FOUND)
mark_as_advanced(
BUILD_GMOCK BUILD_GTEST BUILD_SHARED_LIBS
gmock_build_tests gtest_build_samples gtest_build_tests
gtest_disable_pthreads gtest_force_shared_crt gtest_hide_internal_symbols
)
enable_testing()
macro(package_add_test TESTNAME)
# create an exectuable in which the tests will be stored
add_executable(${TESTNAME} ${ARGN})
# link the Google test infrastructure, mocking library, and a default main fuction to
target_link_libraries(${TESTNAME} gtest gtest_main -lpthread -lm api libdynuiprefresher ${CURL_LIBRARIES} ${LIBCONFIG++_LIBRARIES})
# see https://cmake.org/cmake/help/v3.10/module/GoogleTest.html for more options to pass to it
gtest_discover_tests(${TESTNAME})
add_custom_command(TARGET build-test
POST_BUILD
COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target ${TESTNAME}
COMMAND "bin/${TESTNAME}" --gtest_output=xml:${TESTNAME}-report.xml)
endmacro()
add_custom_target(build-test
DEPENDS ${PROJECT_NAME}
COMMENT "Testing ${PROJECT_NAME}")
package_add_test(test1 tests/UnitTest.cpp ${SOURCE})
else ()
message(STATUS "GTEST environment not found!")
endif ()
ENDIF ()

View File

@ -1,19 +0,0 @@
FROM gcc:latest
MAINTAINER luki42
RUN \
\
# Install texlive
echo "instaling cmake" && \
apt-get update && \
apt-get install -y --no-install-recommends cmake libgtest-dev && \
echo "installing build dependencies" && \
apt-get install -y --no-install-recommends libcurl4-openssl-dev libconfig++-dev && \
echo "installing packaging tools" && \
apt-get install -y --no-install-recommends dpkg rpm && \
# clean up
apt-get clean
# Expose /home as workin dir
WORKDIR /home
VOLUME ["/home"]

View File

@ -1,20 +0,0 @@
FROM fedora:33
MAINTAINER luki42
RUN \
\
# Install texlive
echo "instaling cmake" && \
dnf install -y mingw64-gcc-c++ mingw64-curl-static mingw64-qt5-qtbase wget cmake make tar xz mingw32-nsis gtest gtest-devel && \
wget http://repo.msys2.org/mingw/x86_64/mingw-w64-x86_64-libconfig-1.7.2-1-any.pkg.tar.xz && \
tar -xf mingw-w64-x86_64-libconfig-1.7.2-1-any.pkg.tar.xz && \
mv ./mingw64/bin/* /usr/x86_64-w64-mingw32/sys-root/mingw/bin && \
mv ./mingw64/include/* /usr/x86_64-w64-mingw32/sys-root/mingw/include && \
mv ./mingw64/lib/*.a /usr/x86_64-w64-mingw32/sys-root/mingw/lib && \
mv ./mingw64/lib/cmake/* /usr/x86_64-w64-mingw32/sys-root/mingw/lib/cmake && \
rm -Rv mingw-w64-x86_64-libconfig-1.7.2-1-any.pkg.tar.xz mingw64 && \
#cleanup
dnf clean dbcache && dnf clean packages
# Expose /home as workin dir
WORKDIR /home
VOLUME ["/home"]

121
README.md
View File

@ -1,121 +0,0 @@
[![pipeline status](http://gitlab.heili.eu/lukas/dynuiprefresher/badges/master/pipeline.svg)](http://gitlab.heili.eu/lukas/dynuiprefresher/-/commits/master)
# DynuIPRefresher
A lightweight C++ application to setup a service for refreshing a dynamic IP to the Dynu servers.
Dynu.com is a free DDns service and provides an API.
There is also a GUI for Windows Users and beginners.
## Installation
Download the latest Release at [Release_Page](https://github.com/Lukas-Heiligenbrunner/DynuIPRefresher/releases).
I'm providing executables for Debian/Ubuntu (.deb) and RHEL/Debian (.rpm).
But you can still compile the code my your own (see build section).
## Configuration
There is a configuration file `/etc/dynuiprefresher.cfg` where you have to specify the DYNU API key (get it from their homepage), the domainid and your domain.
Furthermore, you can optionally specify a Telegram API key and a Chat ID if you want to be notfied when your local ip changes.
To enable and start the service:
`systemctl enable dynuiprefresher.service` and `systemctl start dynuiprefresher.service`
## Usage
First of all configure the right keys in the `/etc/dynuiprefresher.cfg` or `%appdata%\DynuIpRefresher\dynuiprefresher.cfg` config file.
Afterwards use the following options:
```
help page:
[-h] [--help] print this help page
[-v] [--version] print the software version
[-f] [--force] force refresh of ip
[-l] [--loop] infinite loop to refresh ip every five minutes
[-c] [--checkconfig] validate configuration
[-ip] [--currentip] get current global ip
[no argument] normal ip check and refresh
```
### GUI
You can also build the grapical user inteface if you want.
There you can manually trigger a refresh in a gui and set all the config parameters.
Home Page:
![couldn't load image](https://i.ibb.co/syDwWQg/Screenshot-20200608-104253.png)
Config Page:
![couldn't load image](https://i.ibb.co/89vnJXY/Screenshot-20200608-104308.png)
## Build
## Basic Build
### Download source files
`git clone https://github.com/Lukas-Heiligenbrunner/DynuIPRefresher.git`
### install build dependencies
`libcurl`
`libconfig`
#### Debian:
`apt install libcurl4-openssl-dev`
#### Fedora:
`dnf install libcurl-devel libconfig-devel`
#### Alpine Linux:
Compiler dependencies:
`apk add make cmake g++`
Lib dependencies:
`apk add libcurl curl-dev libconfig libconfig-dev`
Packaging dependencies:
`apk add dpkg rpm`
#### dependencies for package build
`dpkg` --> debian/ubuntu package
`rpmbuild` --> Fedora/RedHat/CentOS package
### cmake project
cd into downloaded files and Generate makefiles:
`cmake -S . -B build`
### compile project
`make`
[root] install it to the system
`make install`
(optional) create Linux packages
`make package`
### GUI Build
please use the predefined Docker-Image here:
[DockerHub](https://hub.docker.com/repository/docker/luki42/dynuiprefresher_build)
### Windows cross build
Set Winbuild flag in CMakeList.txt.
Dependencies:
* MinGW Compiler
* MinGW-libcurl
* MinGW-libconfig++
Optional dependencies
* NSIS Pack tool (for creating installer)
* doxygen (for generating html doc)
The Simplest way to install all dependencies is the preconfigured Docker-Image:
[DockerHub](https://hub.docker.com/repository/docker/luki42/dynuiprefresher_build)
`make package` will pack it into a NSIS installer for Windows.

View File

@ -1,12 +0,0 @@
# Dynu IP refresher config
# 2020
# Lukas Heiligenbrunner
## DYNU API Config
dynuapikey = ""
domainid = ""
domainname = ""
## Telegram API Config (optional)
#telegramApiKey = ""
#chatId = ""

View File

@ -1,383 +0,0 @@
#OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doc_doxygen/
#INPUT = @CMAKE_CURRENT_SOURCE_DIR@/inc/ @CMAKE_CURRENT_SOURCE_DIR@/../docs
# Doxyfile 1.8.15
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "My Project"
PROJECT_NUMBER =
PROJECT_BRIEF =
PROJECT_LOGO =
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doc_doxygen/
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
OUTPUT_TEXT_DIRECTION = None
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 0
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/inc/
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.idl \
*.ddl \
*.odl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.cs \
*.d \
*.php \
*.php4 \
*.php5 \
*.phtml \
*.inc \
*.m \
*.markdown \
*.md \
*.mm \
*.dox \
*.py \
*.pyw \
*.f90 \
*.f95 \
*.f03 \
*.f08 \
*.f \
*.for \
*.tcl \
*.vhd \
*.vhdl \
*.ucf \
*.qsf \
*.ice
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 126
HTML_COLORSTYLE_SAT = 0
HTML_COLORSTYLE_GAMMA = 240
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = YES
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME =
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = \makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

View File

@ -1,113 +0,0 @@
/**
* A static class to manage the configuration file, read/write parameters to it.
*
* @author Lukas Heiligenbrunner
* @date 11.02.2020
*/
#pragma once
#include <string>
class Config {
public:
/**
* read configuration out of config file
*
* @return success of config read
*/
static bool readConfig();
/**
* save back configuration to file
*
* @return success of config write
*/
static bool saveConfig();
/**
* validate config file
*
* @return validity of config file
*/
static bool validateConfig();
/**
* check if telegram credentials in config are set
* @return is supported?
*/
static bool isTelegramSupported();
/** Getters **/
/**
* encapsulated getter for DynuApiKey
* @return api key
*/
static const std::string &getDynuapikey();
/**
* encapsulated getter for DomainId
* @return DomainId
*/
static const std::string &getDomainid();
/**
* encapsulated getter for Domainname
* @return Domainname
*/
static const std::string &getDomainname();
/**
* encapsulated getter for TelegramApiKey
* @return TelegramApiKey
*/
static const std::string &getTelegramApiKey();
/**
* encapsulated getter for ChatId
* @return ChatId
*/
static const std::string &getChatId();
/**
* set all parameters without telegram support
*
* @param domainname Dynu Domain name
* @param dynuapikey Dynu api key
* @param domainid Dynu domain id
*/
static void setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid);
/**
* set all parameters with telegram support
*
* @param domainname Dynu Domain name
* @param dynuapikey Dynu api key
* @param domainid Dynu domain id
* @param telegramApiKey Telegram api key
* @param chatId Telegram chat id
*/
static void setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid,
const std::string &telegramApiKey, const std::string &chatId);
private:
/**
* private constructor --> don't allow instance of this class
*/
Config() = default;
/**
* helper variable for managing telegram Support
*/
static bool telegramSupport;
/**
* helper variables for storing keys and ids
*/
static std::string dynuapikey;
static std::string domainid; //id of the dynu domain
static std::string domainname;
static std::string telegramApiKey;
static std::string chatId;
};

View File

@ -1,26 +0,0 @@
/**
* Read and write current ip to a temp file to remember last ip until restart
*
* @author Lukas Heiligenbrunner
* @date 05.05.2019
*/
#pragma once
#include <string>
class FileLogger {
public:
/**
* safe ip to temp file
* @param ip ip address to save
*/
void safeip(std::string ip);
/**
* read ip from file
* @return read ip
*/
std::string readip();
};

View File

@ -1,33 +0,0 @@
/**
* IPrefresher library
* - start checking ip once
* - or in loop mode
*
* @author Lukas Heiligenbrunner
* @date 06.04.2019
*/
#pragma once
namespace IPRefresher {
/**
* Status return-codes for startUpService
*/
namespace Status_Code {
const int SUCCESS = 1;
const int ERROR = -1;
const int ERROR_NO_INTERNET = -2;
const int NOREFRESH = 0;
}
/**
* refresh ip address on Dynu server
*/
bool checkIPAdress(bool force);
/**
* start the service in loop mode
* every 5 minutes the ip is checked an refreshed (needed for .service)
*/
void startUpService(int interval = 300);
}

View File

@ -1,22 +0,0 @@
/**
* A helper class for general IP String actions
*
* @author Lukas Heiligenbrunner
* @date 07.05.2020
*/
#pragma once
#include <string>
class IpHelper {
public:
/**
* check if ip is valid
* @param ip ip address to test
* @return validity
*/
static bool isIpValid(const std::string& ip);
private:
};

View File

@ -1,51 +0,0 @@
/**
* Fancy console log output format
* todo log level support
*
* @author Lukas Heiligenbrunner
* @date 26.10.2019
*/
#pragma once
#include <string>
class Logger {
public:
/**
* a debug message
* @param message message
*/
static void debug(std::string message);
/**
* a default message
* @param message message
*/
static void message(std::string message);
/**
* a warning message
* @param message message
*/
static void warning(std::string message);
/**
* a error message
* @param message message
*/
static void error(std::string message);
/**
* a log message with manual level set
* @param message message
* @param level loglevel (1-4) or predefined labels
*/
static void log(const std::string &message, int level);
static const int Debug = 4;
static const int Message = 3;
static const int Warning = 2;
static const int Error = 1;
};

View File

@ -1,40 +0,0 @@
/**
* API class
* - manages all curl download stuff
* - easy POST/GET requests
*
* @author Lukas Heiligenbrunner
* @date 06.04.2019
*/
#pragma once
#include "Hashmap.h"
#include <string>
class API {
public:
/**
* Simple API get request
* @param myurl api url
* @return return string of server
*/
std::string request(std::string myurl);
/**
* complex request with post/get and header information support
* @param myurl base request url
* @param post boolean (false=get)
* @param map post/get fields
* @param headers header fields
* @return return string of server
*/
std::string request(std::string myurl,
bool post,
Hashmap<std::string, std::string> &map,
std::vector<std::string> &headers);
private:
static size_t write_data(void *buffer, size_t size, size_t buffersize, FILE *stream);
};

View File

@ -1,44 +0,0 @@
/**
* Dynu API - Refresh the IP
*
* @author Lukas Heiligenbrunner
* @date 18.06.2019
*/
#pragma once
#include "API.h"
class DynuAPI : API {
public:
/**
* refresh the ip of domain on Dynu server
* @param ip new ip
* @return request status
*/
bool refreshIp(std::string ip);
/**
* init Telegram api with apikey and chatid
* @param dynuApiKey Dynu Api key
* @param domainId ID of domain received by Dynu
* @param domainName domainname to refresh
*/
void init(const std::string &dynuApiKey, const std::string &domainId, const std::string &domainName);
private:
/**
* Dynu API Key
*/
std::string dynuapikey;
/**
* Dynu Domain ID
*/
std::string domainid;
/**
* Domain name eg. "mydomain.dynu.net"
*/
std::string domainname;
};

View File

@ -1,21 +0,0 @@
/**
* IPAPI for getting global ip of current network
*
* @author Lukas Heiligenbrunner
* @date 18.06.2019
*/
#pragma once
#include "API.h"
#include <string>
class IPAPI : API {
public:
/**
* get global ip of current internet connection
* @return global ip
*/
std::string getGlobalIp();
};

View File

@ -1,32 +0,0 @@
/**
* Telegram API for sending message to specific chat
*
* @author Lukas Heiligenbrunner
* @date 08.05.2019
*/
#pragma once
#include "API.h"
#include <string>
class TelegramAPI : API {
public:
/**
* send telegram Message to predefined destination
* @param text message
*/
int sendMessage(const std::string &text);
/**
* init Telegram api with apikey and chatid
* @param apikey recieved API key
* @param chatid chatid where bot should post into
*/
void init(std::string apikey, std::string chatid);
private:
std::string apikey;
std::string chatid;
};

View File

@ -1,63 +0,0 @@
/**
* Main GUI controller - User IO handlings
*
* @author Lukas Heiligenbrunner
* @date 09.05.2020
*/
#pragma once
#include <QtWidgets/QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
/**
* constructor with basic initializations
*/
explicit MainWindow();
/**
* destruct all gui elements
*/
~MainWindow();
private:
Ui::MainWindow *ui;
/**
* all static initializations of custom gui elements
*/
void initGui();
private slots:
/**
* executed click handler for config button
*/
void checkConfigBtn();
/**
* executed click handler for refresh btn
*/
void refreshIPBtn();
/**
* executed click handler for save config btn
*/
void saveConfigBtn();
signals:
/**
* append a String line to the Log field
*
* @param QString string to be appended
*/
void appendLogField(QString);
};

View File

@ -1,12 +0,0 @@
[Unit]
Description=IP Refresher
After=network.target
[Service]
ExecStart=dynuiprefresher -l
WorkingDirectory=/root
StandardOutput=inherit
StandardError=inherit
Restart=always
User=root
[Install]
WantedBy=multi-user.target

View File

@ -1,28 +1,40 @@
#include "api/API.h" //
// Created by lukas on 06.04.19.
//
#include <sstream> #include "API.h"
#include <string>
#include <iostream>
#include <stdio.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <sstream>
#include "Hashmap.h"
std::string API::request(std::string myurl) { std::string API::request(std::string myurl) {
Hashmap<std::string, std::string> map; Hashmap<std::string,std::string> map;
std::vector<std::string> str; std::vector<std::string> str;
return request(std::move(myurl), false, map, str); return request(myurl,false,map,str);
} }
std::string std::string API::request(std::string myurl, bool post, Hashmap<std::string,std::string> &map, std::vector<std::string> headers) {
API::request(std::string myurl, bool post, Hashmap<std::string, std::string> &map, std::vector<std::string> &headers) {
CURL *curl; CURL *curl;
CURLcode res;
curl = curl_easy_init(); curl = curl_easy_init();
struct curl_slist *list = nullptr; struct curl_slist *list = NULL;
for (int j = 0; j < headers.size(); ++j) { for (int j = 0; j < headers.size(); ++j) {
list = curl_slist_append(list, headers.at((unsigned long) (j)).c_str()); list = curl_slist_append(list, headers.at(j).c_str());
} }
std::string readString; std::string readString;
if (curl) { if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, myurl.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
@ -30,40 +42,38 @@ API::request(std::string myurl, bool post, Hashmap<std::string, std::string> &ma
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
if (post) { if(post){
std::stringstream poststring; std::stringstream poststring;
poststring << "{"; poststring << "{";
for (int i = 0; i < map.size(); i++) { for (int i = 0; i < map.size(); i++) {
poststring << "\"" + map.getKey(i) << "\": \"" + map.getValue(i) << "\""; poststring << "\""+map.getKey(i) << "\": \""+map.getValue(i) << "\"";
if (i < map.size() - 1) { if(i < map.size()-1){
poststring << ", "; poststring << ", ";
} }
} }
poststring << "}"; poststring << "}";
// std::cout << "post string: " << poststring.str() << "\n";
curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, poststring.str().c_str()); curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS, poststring.str().c_str());
} else { }else{
if (map.size() > 0) {
std::string getstring; std::string getstring;
for (int i = 0; i < map.size(); i++) { for(int i =0; i< map.size();i++){
getstring += map.getKey(i) + "=" + map.getValue(i); getstring+=map.getKey(i)+"="+map.getValue(i);
if (i < map.size() - 1) { if(i < map.size()-1){
getstring += "&"; getstring+="&";
} }
} }
myurl += "?" + getstring; myurl+="?"+getstring;
}
} }
curl_easy_setopt(curl, CURLOPT_URL, myurl.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readString); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readString);
curl_easy_perform(curl); res = curl_easy_perform(curl);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
} }
@ -71,6 +81,6 @@ API::request(std::string myurl, bool post, Hashmap<std::string, std::string> &ma
} }
size_t API::write_data(void *contents, size_t size, size_t nmemb, FILE *stream) { size_t API::write_data(void *contents, size_t size, size_t nmemb, FILE *stream) {
((std::string *) stream)->append((char *) contents, size * nmemb); ((std::string*)stream)->append((char*)contents, size * nmemb);
return size * nmemb; return size * nmemb;
} }

22
src/API.h Normal file
View File

@ -0,0 +1,22 @@
//
// Created by lukas on 06.04.19.
//
#ifndef IPREFRESHER_API_H
#define IPREFRESHER_API_H
#include <string>
#include "Hashmap.h"
class API {
public:
std::string request(std::string myurl);
std::string request(std::string myurl, bool post, Hashmap<std::string,std::string> &map,std::vector<std::string> headers);
private:
static size_t write_data(void *buffer, size_t size, size_t buffersize, FILE *stream);
};
#endif //IPREFRESHER_API_H

View File

@ -1,182 +0,0 @@
#include "Config.h"
#include "Logger.h"
#include "StaticData.h"
#include <iostream>
#include <cstring>
#include <fstream>
#include <libconfig.h++>
#include <sys/stat.h>
std::string Config::dynuapikey;
std::string Config::domainid; //id of the dynu domain
std::string Config::domainname;
std::string Config::telegramApiKey;
std::string Config::chatId;
bool Config::telegramSupport;
bool Config::readConfig() {
libconfig::Config cfg;
try {
cfg.readFile(std::string(StaticData::ConfigDir + StaticData::ConfName).c_str());
}
catch (const libconfig::FileIOException &fioex) {
std::cout << "I/O error while reading config file." << std::endl << "creating new config file!" << std::endl;
// check if config folder exists
struct stat info{};
if (stat(StaticData::ConfigDir.c_str(), &info) != 0) {
Logger::warning("The config folder doesn't exist. Trying to create it.");
// mkdir command is different defined for windows
#ifdef __unix
int check = mkdir(StaticData::ConfigDir.c_str(), 777);
#else
int check = mkdir(StaticData::ConfigDir.c_str());
#endif
// check if directory is created or not
if (!check)
Logger::message("config directory successfully created. ");
else
Logger::error("unable to create config directory.");
} else if (info.st_mode & S_IFDIR) {
Logger::debug("config directory exists already");
} else {
Logger::error("A file exists with the same name as the config dir should be");
}
std::ofstream myfile;
myfile.open(StaticData::ConfigDir + StaticData::ConfName);
if (myfile.is_open()) {
myfile << StaticData::SAMPLECONFIG;
myfile.close();
} else {
Logger::error("error creating file");
}
return false;
}
catch (const libconfig::ParseException &pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << std::endl;
return false;
}
try {
// needed parameters
dynuapikey = (std::string) cfg.lookup("dynuapikey");
domainid = (std::string) cfg.lookup("domainid");
domainname = (std::string) cfg.lookup("domainname");
// optional parameters
telegramApiKey = (std::string) cfg.lookup("telegramApiKey");
chatId = (std::string) cfg.lookup("chatId");
telegramSupport = true;
}
catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
}
}
// check if needed values aren't empty
return !(Config::dynuapikey.empty() || Config::domainid.empty() || Config::domainname.empty());
}
bool Config::saveConfig() {
// todo save config
return false;
}
bool Config::validateConfig() {
libconfig::Config cfg;
try {
Logger::message("reading config file");
cfg.readFile(std::string(StaticData::ConfigDir + StaticData::ConfName).c_str());
}
catch (const libconfig::FileIOException &fioex) {
Logger::warning("config file doesn't exist or permission denied!");
return false;
}
catch (const libconfig::ParseException &pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << std::endl;
return false;
}
Logger::message("Syntax and Permission is OK");
try {
// needed parameters
if (((std::string) cfg.lookup("dynuapikey")).empty()) {
Logger::warning("required parameter \"dynuapikey\" seems to be empty.");
return false;
}
if (((std::string) cfg.lookup("domainid")).empty()) {
Logger::warning("required parameter \"domainid\" seems to be empty.");
return false;
}
if (((std::string) cfg.lookup("domainname")).empty()) {
Logger::warning("required parameter \"domainname\" seems to be empty.");
return false;
}
// optional parameters
cfg.lookup("telegramApiKey");
cfg.lookup("chatId");
telegramSupport = true;
}
catch (const libconfig::SettingNotFoundException &nfex) {
// triggered if setting is missing in config
if (!(std::strcmp("telegramApiKey", nfex.getPath()) == 0 || std::strcmp("chatId", nfex.getPath()) == 0)) {
std::cerr << "No '" << nfex.getPath() << "' setting in configuration file." << std::endl;
return false;
} else {
Logger::message("no Telegram support - fields in config not set");
telegramSupport = false;
}
}
return true;
}
bool Config::isTelegramSupported() {
return telegramSupport;
}
const std::string &Config::getDynuapikey() {
return dynuapikey;
}
const std::string &Config::getDomainid() {
return domainid;
}
const std::string &Config::getDomainname() {
return domainname;
}
const std::string &Config::getTelegramApiKey() {
return telegramApiKey;
}
const std::string &Config::getChatId() {
return chatId;
}
void Config::setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid) {
Config::domainname = domainname;
Config::dynuapikey = dynuapikey;
Config::domainid = domainid;
}
void Config::setValues(const std::string &domainname, const std::string &dynuapikey, const std::string &domainid, const std::string &telegramApiKey, const std::string &chatId) {
setValues(domainname, dynuapikey, domainid);
Config::telegramApiKey = telegramApiKey;
Config::chatId = chatId;
}

View File

@ -1,27 +0,0 @@
#include "FileLogger.h"
#include "IpHelper.h"
#include "StaticData.h"
#include <fstream>
#include <iostream>
void FileLogger::safeip(std::string ip) {
std::ofstream out;
out.open(StaticData::TempFilePath + "temp-dynuiprefresher.txt", std::ios::out);
out << ip;
out.close();
}
std::string FileLogger::readip() {
std::ifstream in;
in.open(StaticData::TempFilePath + "temp-dynuiprefresher.txt", std::ios::in);
std::string ip;
in >> ip;
// when received ip has no . return 0.0.0.0
return (IpHelper::isIpValid(ip) ? ip : "0.0.0.0");
}

View File

@ -1,43 +1,20 @@
/** //
* A Hashmap class for easier Key-Value maps // Created by lukas on 07.04.19.
* //
* @author Lukas Heiligenbrunner
* @date 07.04.2019 #ifndef QT5PROJECT_HASHMAP_H
*/ #define QT5PROJECT_HASHMAP_H
#pragma once
#include <iostream> #include <iostream>
#include <vector> #include <vector>
template<class keytype, class valuetype> template <class keytype,class valuetype> class Hashmap {
class Hashmap {
public: public:
/** void add(keytype key,keytype value);
* add key-value pair to hashmap
* @param key keyvalue
* @param value valuevalue
*/
void add(keytype key, keytype value);
/**
* get key of specific position
* @param position int position
* @return responding key object
*/
keytype getKey(int position); keytype getKey(int position);
/**
* get value of specific position
* @param position int position
* @return responding value object
*/
valuetype getValue(int position); valuetype getValue(int position);
/**
* get size of Hashmap
* @return size of Hashmap
*/
int size(); int size();
private: private:
@ -63,5 +40,8 @@ valuetype Hashmap<keytype, valuetype>::getValue(int position) {
template<class keytype, class valuetype> template<class keytype, class valuetype>
int Hashmap<keytype, valuetype>::size() { int Hashmap<keytype, valuetype>::size() {
return (int) (keys.size()); return keys.size();
} }
#endif //QT5PROJECT_HASHMAP_H

View File

@ -1,71 +0,0 @@
#include "IPRefresher.h"
#include "FileLogger.h"
#include "api/IPAPI.h"
#include "api/DynuAPI.h"
#include "api/TelegramAPI.h"
#include "Config.h"
#include "StaticData.h"
#include "IpHelper.h"
#include <chrono>
#include <thread>
#include <Logger.h>
bool IPRefresher::checkIPAdress(bool force) {
FileLogger logger;
IPAPI ipapi;
std::string ip = ipapi.getGlobalIp();
if (ip.empty()) {
//no internet connection (or other error)
Logger::warning("no internet connection");
return Status_Code::ERROR_NO_INTERNET;
} else if (!IpHelper::isIpValid(ip)) {
// error when ip doesn't contain a :
Logger::warning("an error occured when getting the global ip");
return Status_Code::ERROR;
} else {
std::string oldip = logger.readip();
if (oldip == ip && !force) {
Logger::message("no change -- ip: " + ip);
return Status_Code::NOREFRESH;
} else {
Logger::message("ip changed! -- from :" + oldip + "to: " + ip);
DynuAPI dynu;
dynu.init(Config::getDynuapikey(), Config::getDomainid(), Config::getDomainname());
// actual refresh of IP in api - here
bool result = dynu.refreshIp(ip);
if (result && Config::isTelegramSupported()) {
TelegramAPI tele;
tele.init(Config::getTelegramApiKey(), Config::getChatId());
tele.sendMessage(oldip + " moved to " + ip);
} else if (!result) {
//error
Logger::error("failed to write ip to dynu api!");
return Status_Code::ERROR;
}
logger.safeip(ip);
return result ? Status_Code::SUCCESS : Status_Code::ERROR;
}
}
}
void IPRefresher::startUpService(int interval) {
Logger::message("startup of service");
Logger::message("Version: " + StaticData::VERSION);
while (true) {
Logger::message("starting check");
if (Config::readConfig()) {
checkIPAdress(false);
} else {
std::cout << "incorrect credentials!" << std::endl;
}
std::this_thread::sleep_for(std::chrono::milliseconds(interval * 1000));
}
}

View File

@ -1,7 +0,0 @@
#include <regex>
#include "IpHelper.h"
bool IpHelper::isIpValid(const std::string& ip) {
const std::regex rgx(R"(^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)");
return (std::regex_match(ip, rgx));
}

View File

@ -1,46 +1,49 @@
//
// Created by lukas on 05.05.19.
//
#include <fstream>
#include <ctime>
#include <iostream>
#include <sstream>
#include "Logger.h" #include "Logger.h"
#include <sstream> void Logger::safeip(std::string ip) {
#include <iostream> std::ofstream out;
out.open("ip.txt",std::ios::out);
void Logger::debug(const std::string message) { out << ip;
log(message, Logger::Debug);
out.close();
} }
void Logger::message(const std::string message) { std::string Logger::readip() {
log(message, Logger::Message); std::ifstream in;
in.open("ip.txt",std::ios::in);
std::string ip;
in >> ip;
return ip;
} }
void Logger::warning(const std::string message) { void Logger::logToLogfile(std::string text) {
log(message, Logger::Warning); std::ofstream out;
} out.open("dynurefresher.log",std::ios::out | std::ios::app);
void Logger::error(const std::string message) {
log(message, Logger::Error);
}
void Logger::log(const std::string &message, int level) { std::time_t t = std::time(0); // get time now
std::stringstream out; std::tm* now = std::localtime(&t);
out << "[";
switch (level) {
case Debug:
out << "DEBUG";
break;
case Message:
out << "MESSAGE";
break;
case Warning:
out << "WARNING";
break;
case Error:
out << "ERROR";
break;
default:
out << "UNDEFINED";
break;
}
out << "] ";
out << message;
std::cout << out.str() << std::endl;
}
std::stringstream logline;
logline << "[ "<< (now->tm_year + 1900) << '-' << (now->tm_mon + 1) << '-' << now->tm_mday
<< "_" << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec << " ] " << '\t' << text << std::endl;
out << logline.str();
out.close();
}

18
src/Logger.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by lukas on 05.05.19.
//
#ifndef IPREFRESHER_LOGGER_H
#define IPREFRESHER_LOGGER_H
class Logger {
public:
void logToLogfile(std::string text);
void safeip(std::string ip);
std::string readip();
};
#endif //IPREFRESHER_LOGGER_H

View File

@ -1,22 +0,0 @@
#include "api/DynuAPI.h"
bool DynuAPI::refreshIp(std::string ip) {
Hashmap<std::string, std::string> args;
args.add("name", domainname);
args.add("ipv4Address", ip);
std::vector<std::string> headers;
headers.emplace_back("accept: application/json");
headers.emplace_back("User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com)");
headers.emplace_back("API-Key: " + dynuapikey);
const std::string dynurepl = request("https://api.dynu.com/v2/dns/" + domainid, true, args, headers);
return (dynurepl == "{\"statusCode\":200}");
}
void DynuAPI::init(const std::string &dynuApiKey, const std::string &domainId, const std::string &domainName) {
this->dynuapikey = dynuApiKey;
this->domainid = domainId;
this->domainname = domainName;
}

View File

@ -1,11 +0,0 @@
#include <IpHelper.h>
#include <Logger.h>
#include "api/IPAPI.h"
std::string IPAPI::getGlobalIp() {
const std::string ip = request("https://api.ipify.org");
if(!IpHelper::isIpValid(ip))
Logger::warning("no valid ip returned from ipapi");
return ip;
}

View File

@ -1,23 +0,0 @@
#include "api/TelegramAPI.h"
#include "Logger.h"
int TelegramAPI::sendMessage(const std::string &text) {
Hashmap<std::string, std::string> args;
args.add("chat_id", chatid);
args.add("text", text);
std::vector<std::string> headers;
std::string reply = request("https://api.telegram.org/bot" + apikey + "/sendmessage", false, args, headers);
if (reply.find("\"error_code\"") != SIZE_MAX) {
Logger::error("failed to send the Telegram Message");
return -1;
}
return 1;
}
void TelegramAPI::init(const std::string apikey, const std::string chatid) {
this->apikey = apikey;
this->chatid = chatid;
}

View File

@ -1,129 +0,0 @@
#include "inc/gui/MainWindow.h"
#include "ui_mainwindow.h"
#include "api/IPAPI.h"
#include "IPRefresher.h"
#include "Config.h"
#include "Logger.h"
#include <thread>
MainWindow::MainWindow() : QMainWindow(), ui(new Ui::MainWindow) {
ui->setupUi(this);
// initialize gui with start parameters
initGui();
connect(ui->buttonCheckConfig, SIGNAL(clicked()), this, SLOT(checkConfigBtn()));
connect(ui->buttonRefreshIP, SIGNAL(clicked()), this, SLOT(refreshIPBtn()));
connect(ui->buttonSaveConfig, SIGNAL(clicked()), this, SLOT(saveConfigBtn()));
connect(this, SIGNAL(appendLogField(QString)), ui->textLog, SLOT(appendPlainText(QString)));
}
MainWindow::~MainWindow() {
// todo check if disconnects are really necessary
disconnect(ui->buttonCheckConfig);
disconnect(ui->buttonRefreshIP);
this->destroy();
delete ui;
}
void MainWindow::checkConfigBtn() {
Logger::message("checking config!");
appendLogField("checking config!");
if (Config::validateConfig()) {
Logger::message("Config file is OK");
appendLogField("Config file is OK");
ui->labelConfig->setText("Config is: OK");
} else {
Logger::error("There are errors in config file!");
appendLogField("There are errors in config file!");
}
appendLogField("");
}
void MainWindow::refreshIPBtn() {
Logger::message("start refreshing Dynu IP.");
appendLogField("");
appendLogField("start refreshing Dynu IP.");
new std::thread([this]() {
if (Config::readConfig()) {
int code = IPRefresher::checkIPAdress(false);
switch (code) {
case IPRefresher::Status_Code::SUCCESS:
appendLogField("successfully refreshed IP!");
break;
case IPRefresher::Status_Code::NOREFRESH:
appendLogField("IP is already correct.");
break;
case IPRefresher::Status_Code::ERROR_NO_INTERNET:
appendLogField("Error: No Internet connection");
break;
case IPRefresher::Status_Code::ERROR:
appendLogField("An error occured while refreshing.");
break;
default:
appendLogField("An unknown error code occured");
}
} else {
std::cout << "incorrect credentials!" << std::endl;
}
Logger::message("Finished refreshing Dynu IP.");
this->appendLogField("Finished refreshing Dynu IP.");
});
}
void MainWindow::saveConfigBtn() {
if (ui->telegramsupportCheckbox->isChecked()) {
Config::setValues(
ui->domainnameedit->text().toStdString(),
ui->dynuapikeyedit->text().toStdString(),
ui->domainidedit->text().toStdString(),
ui->telegramapikeyedit->text().toStdString(),
ui->chatidedit->text().toStdString());
} else {
Config::setValues(
ui->domainnameedit->text().toStdString(),
ui->dynuapikeyedit->text().toStdString(),
ui->domainidedit->text().toStdString());
}
Config::saveConfig();
}
void MainWindow::initGui() {
// needs to be defined with new -- would be termintated after the constructor call.
new std::thread([this]() {
IPAPI ipapi;
std::string ip = ipapi.getGlobalIp();
Logger::message("Current global IP: " + ip);
std::string msg = "Your current global IP: " + ip;
this->ui->labelCurrentIP->setText(msg.c_str());
});
// set config info label and initial check if config is valid
ui->labelConfig->setText(Config::validateConfig() ? "Config is: OK" : "Config is: NOT OK");
if (Config::readConfig()) {
ui->dynuapikeyedit->setText(Config::getDynuapikey().c_str());
ui->domainidedit->setText(Config::getDomainid().c_str());
ui->domainnameedit->setText(Config::getDomainname().c_str());
if (Config::isTelegramSupported()) {
ui->telegramsupportCheckbox->setCheckState(Qt::Checked);
ui->telegramapikeyedit->setText(Config::getTelegramApiKey().c_str());
ui->chatidedit->setText(Config::getChatId().c_str());
} else {
ui->telegramsupportCheckbox->setCheckState(Qt::Unchecked);
ui->telegramapikeyedit->setDisabled(true);
ui->chatidedit->setDisabled(true);
}
} else {
// todo duplicate code with above
ui->telegramsupportCheckbox->setCheckState(Qt::Unchecked);
ui->telegramapikeyedit->setDisabled(true);
ui->chatidedit->setDisabled(true);
}
}

View File

@ -1,320 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>823</width>
<height>618</height>
</rect>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">/*background-color: rgb(69, 196, 255);</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPlainTextEdit" name="textLog">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>40</x>
<y>410</y>
<width>741</width>
<height>191</height>
</rect>
</property>
<property name="cursor" stdset="0">
<cursorShape>IBeamCursor</cursorShape>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>40</x>
<y>380</y>
<width>64</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Log:</string>
</property>
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="geometry">
<rect>
<x>40</x>
<y>20</y>
<width>741</width>
<height>351</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="basic">
<attribute name="title">
<string>Basic</string>
</attribute>
<widget class="QLabel" name="labelCurrentIP">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>301</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Your current global IP:</string>
</property>
</widget>
<widget class="QLabel" name="labelConfig">
<property name="geometry">
<rect>
<x>20</x>
<y>70</y>
<width>141</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Config is: undefined</string>
</property>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>20</x>
<y>120</y>
<width>231</width>
<height>151</height>
</rect>
</property>
<property name="title">
<string>Actions</string>
</property>
<widget class="QPushButton" name="buttonCheckConfig">
<property name="geometry">
<rect>
<x>30</x>
<y>50</y>
<width>91</width>
<height>33</height>
</rect>
</property>
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="text">
<string>Check Config</string>
</property>
</widget>
<widget class="QPushButton" name="buttonRefreshIP">
<property name="geometry">
<rect>
<x>30</x>
<y>100</y>
<width>91</width>
<height>33</height>
</rect>
</property>
<property name="text">
<string>Refresh IP</string>
</property>
</widget>
</widget>
</widget>
<widget class="QWidget" name="config">
<attribute name="title">
<string>Config</string>
</attribute>
<widget class="QCheckBox" name="telegramsupportCheckbox">
<property name="geometry">
<rect>
<x>30</x>
<y>120</y>
<width>181</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Telegram Notifications</string>
</property>
</widget>
<widget class="QPushButton" name="buttonSaveConfig">
<property name="geometry">
<rect>
<x>630</x>
<y>270</y>
<width>91</width>
<height>33</height>
</rect>
</property>
<property name="text">
<string>Save Config</string>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>30</x>
<y>20</y>
<width>101</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Dynu API Key</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>460</x>
<y>20</y>
<width>111</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Domain ID</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>30</x>
<y>170</y>
<width>131</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Telegram API Key</string>
</property>
</widget>
<widget class="QLabel" name="label_5">
<property name="geometry">
<rect>
<x>30</x>
<y>240</y>
<width>64</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Chat ID</string>
</property>
</widget>
<widget class="QLineEdit" name="dynuapikeyedit">
<property name="geometry">
<rect>
<x>30</x>
<y>40</y>
<width>211</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="domainidedit">
<property name="geometry">
<rect>
<x>460</x>
<y>40</y>
<width>113</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="chatidedit">
<property name="geometry">
<rect>
<x>30</x>
<y>260</y>
<width>113</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="telegramapikeyedit">
<property name="geometry">
<rect>
<x>30</x>
<y>190</y>
<width>311</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="domainnameedit">
<property name="geometry">
<rect>
<x>280</x>
<y>40</y>
<width>161</width>
<height>31</height>
</rect>
</property>
<property name="placeholderText">
<string>domain.dynu.net</string>
</property>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>280</x>
<y>20</y>
<width>111</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Domainname</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="settings">
<attribute name="title">
<string>Settings</string>
</attribute>
<widget class="QLabel" name="label_7">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>161</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Select your language:</string>
</property>
</widget>
<widget class="QComboBox" name="languageComboBox">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>94</width>
<height>31</height>
</rect>
</property>
</widget>
</widget>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,55 +1,49 @@
#include "StaticData.h" #include <iostream>
#include "IPRefresher.h" #include <ctime>
#include "API.h"
#include "Logger.h" #include "Logger.h"
#include "Config.h"
#include "api/IPAPI.h"
/** int main() {
* application entry point API api;
*/ Logger logger;
int main(int argc, char *argv[]) {
if (argc > 1) {
std::string firstarg(argv[1]); std::string ip = api.request("https://api.ipify.org");
if (firstarg == "-h" || firstarg == "--help") {
std::cout << "help page: " << std::endl << "[-h] [--help] print this help page" << std::endl std::string oldip = logger.readip();
<< "[-v] [--version] print the software version" << std::endl
<< "[-f] [--force] force refresh of ip" << std::endl if(oldip == ip){
<< "[-l] [--loop] infinite loop to refresh ip every five minutes" << std::endl std::cout << "no change -- ip: " << ip << std::endl;
<< "[-c] [--checkconfig] validate configuration" << std::endl logger.logToLogfile("no change -- ip: "+ip);
<< "[-ip] [--currentip] get current global ip" << std::endl } else{
<< "[no argument] normal ip check and refresh" << std::endl; logger.logToLogfile("ip changed! -- from :" + oldip + "to: "+ip);
} else if (firstarg == "-v" || firstarg == "--version") { std::cout << "ip changed! -- from :" << oldip << "to: " << ip << std::endl;
std::cout << "Version " << StaticData::VERSION << std::endl;
} else if (firstarg == "-f" || firstarg == "--force") { //api key: 88vNpMfDhMM2YYDNfWR1DNYfRX9W6fYg
if (Config::readConfig()) {
IPRefresher::checkIPAdress(true); Hashmap<std::string, std::string> args;
} else {
std::cout << "incorrect credentials!" << std::endl; args.add("name","luki.dynu.net");
args.add("ipv4Address",ip);
std::vector<std::string> headers;
headers.push_back("accept: application/json");
headers.push_back("User-Agent: Mozilla/5.0 (compatible; Rigor/1.0.0; http://rigor.com)");
headers.push_back("API-Key: 88vNpMfDhMM2YYDNfWR1DNYfRX9W6fYg");
std::string dynurepl = api.request("https://api.dynu.com/v2/dns/8506047",true, args,headers);
std::cout << "---" << dynurepl << std::endl;
if (dynurepl != "{\"statusCode\":200}"){
logger.logToLogfile(" [ERROR] failed to write ip to dynu api!");
} }
} else if (firstarg == "-l" || firstarg == "--loop") { logger.safeip(ip);
IPRefresher::startUpService(600);
} else if (firstarg == "-c" || firstarg == "--checkconfig") {
if (Config::validateConfig()) {
Logger::message("Config file is OK");
} else {
Logger::error("There are errors in config file!");
return -1;
}
} else if (firstarg == "-ip" || firstarg == "--currentip") {
IPAPI ipapi;
std::cout << "Current global IP: " << ipapi.getGlobalIp() << std::endl;
} else {
Logger::message("wrong arguments! -h for help");
}
} else {
Logger::message("starting check");
if (Config::readConfig()) {
IPRefresher::checkIPAdress(false);
} else {
std::cout << "incorrect credentials!" << std::endl;
}
} }
return 0; return 0;
} }

View File

@ -1,14 +0,0 @@
#include <QApplication>
#include "gui/MainWindow.h"
/**
* application entry point
*/
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("Dynu IP Refresher");
w.show();
return QApplication::exec();
}

View File

@ -1,29 +0,0 @@
//
// Created by lukas on 06.05.20.
//
#include <FileLogger.h>
#include <api/IPAPI.h>
#include "gtest/gtest.h"
/**
* Test if default ip is 0.0.0.0 when last ip file doesn't exist.
*/
TEST(ReadIp, testzeroIpIfNotExists) {
FileLogger logger;
std::string oldip = logger.readip();
ASSERT_EQ(oldip, "0.0.0.0");
}
/**
* Test if default ip is 0.0.0.0 when last ip file doesn't exist.
*/
TEST(IPAPI, testIpAPIcheckIPSyntax) {
IPAPI ipapi;
std::string ip = ipapi.getGlobalIp();
if (ip.find('.') == SIZE_MAX) {
// error when ip doesn't contain a .
ASSERT_TRUE(false);
} else {
ASSERT_TRUE(true);
}
}