Commit cdf7e55c authored by Johannes Schwab's avatar Johannes Schwab

Merge branch 'release/0.1.0'

parents abc4bdce 7c837642
.qmake.stash
Makefile
android-ndk-toolchain
android-sources/AndroidManifest.xml
android-sources/assets/
androidlibs
client/Makefile
client/android-libopenrecipes.so-deployment-settings.json
client/android_arm
client/android_x86
client/img/openrecipes.svg
client/intl/client_de.qm
client/libopenrecipes.so
client/moc/
client/obj/
client/openrecipes
client/qrc_client.cpp
client/target_wrapper.sh
lib/libopenrecipes.a
lib/moc/
lib/obj/
lib/src/config.h
libsodium-*
server/Makefile
server/moc/
server/obj/
server/openrecipesserver
server/protocol.aux
server/protocol.log
server/protocol.pdf
This diff is collapsed.
OpenRecipes is a privacy friendly personal cook book.
Most notable feature is the possibility so synchronize your recipes between multiple devices.
The data is therby end-to-end encrypted between devices.
Other features are:
- Edit your recipes with images
- Calculate ingredients for different number of portions
- Share recipes with friends via the local network (not encrypted, IPv6 only).
The client currently runs at Android, Linux and Windows.
The server only runs on Linux. It needs a mysql compatible database and is configured with an ini style file like this:
[general]
;number of jobs to run in the background (>=1) (optional, default: 2)
jobs=2
[server]
;port to listen for connections
port=44556
[mysql]
;mysql user name
user=your_username
;mysql password
password=your_password
;mysql database
database=yout_database
;host of the mysql server (optional, default: localhost)
host=hostname
;port the mysql server listens to (optional, default: 3306)
port=3306
You also need to apply the latest db schema from server/dbSchema to the database you intend to use.
While the server is running, he will print out some status information when receiving SIGUSR1.
To build from source you will need:
- Qt >= 5.10
- libsodium >= 1.0.12
#!/bin/bash
QT_ANDROID_INSTALLER_SHA256=a214084e2295c9a9f8727e8a0131c37255bf724bfc69e80f7012ba3abeb1f763
## $1 filename, $2 sha256 hash
function check_sha256()
{
echo ${2} "${1}" | sha256sum -c &> /dev/null
}
## $1 filename, $2 sha256 hash, $3 url
function verified_download()
{
FILENAME="$1"
SHA256="$2"
URL="$3"
check_sha256 "${FILENAME}" "${SHA256}" ||
{
rm -rf "${FILENAME}"
wget -O "${FILENAME}" "$URL" ||
{
echo "Failed downloading ${FILENAME} from $URL"
exit 1
}
check_sha256 "${FILENAME}" "${SHA256}" ||
{
echo "SHA256 mismatch for ${FILENAME} from ${URL} expected sha256 ${SHA256} got $(sha256sum ${FILENAME} | awk '{print $1}')"
exit 1
}
}
}
## More information available at https://gitlab.com/relan/provisioners/merge_requests/1 and http://stackoverflow.com/a/34032216
install_qt_android()
{
QT_VERSION_CODE=$(echo $QT_VERSION | tr -d .)
QT_INSTALLER="qt-unified-linux-x64-3.0.2-online.run"
verified_download $QT_INSTALLER $QT_ANDROID_INSTALLER_SHA256 \
http://master.qt.io/archive/online_installers/3.0/${QT_INSTALLER}
chmod a+x ${QT_INSTALLER}
QT_INSTALLER_SCRIPT="qt_installer_script.js"
cat << EOF > "${QT_INSTALLER_SCRIPT}"
function Controller() {
installer.autoRejectMessageBoxes();
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
});
var welcomePage = gui.pageWidgetByObjectName("WelcomePage");
welcomePage.completeChanged.connect(function() {
if (gui.currentPageWidget().objectName == welcomePage.objectName)
gui.clickButton(buttons.NextButton);
});
}
Controller.prototype.WelcomePageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.CredentialsPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.IntroductionPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.TargetDirectoryPageCallback = function() {
gui.currentPageWidget().TargetDirectoryLineEdit.setText("$QT_INSTALL_PATH");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
// You can get these component names by running the installer with the
// --verbose flag. It will then print out a resource tree.
widget.deselectAll();
widget.selectComponent("qt.qt5.$QT_VERSION_CODE.android_armv7");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function() {
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
gui.clickButton(buttons.NextButton);
}
Controller.prototype.StartMenuDirectoryPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function() {
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox)
checkBoxForm.launchQtCreatorCheckBox.checked = false;
gui.clickButton(buttons.FinishButton);
}
EOF
QT_QPA_PLATFORM=minimal ./${QT_INSTALLER} --script ${QT_INSTALLER_SCRIPT}
}
install_qt_android
<?xml version=\'1.0\' encoding=\'utf-8\'?>
<manifest package=\"org.jschwab.openrecipes$$NAMEPOSTFIX\"
xmlns:android=\"http://schemas.android.com/apk/res/android\"
android:versionName=\"$$VERSION\"
android:versionCode=\"1\"
android:installLocation=\"auto\">
<application android:hardwareAccelerated=\"true\"
android:name=\"org.qtproject.qt5.android.bindings.QtApplication\"
android:icon=\"@mipmap/ic_launcher\"
android:roundIcon=\"@mipmap/ic_launcher_round\"
android:label=\"OpenRecipes$$NAMEPOSTFIX\">
<activity android:configChanges=\"orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation\"
android:name=\"org.qtproject.qt5.android.bindings.QtActivity\"
android:label=\"@string/app_name\"
android:screenOrientation=\"unspecified\"
android:theme=\"@style/AppTheme\"
android:launchMode=\"singleTop\">
<intent-filter>
<action android:name=\"android.intent.action.MAIN\"/>
<category android:name=\"android.intent.category.LAUNCHER\"/>
</intent-filter>
<!-- Application arguments -->
<!-- meta-data android:name=\"android.app.arguments\" android:value=\"arg1 arg2 arg3\"/ -->
<!-- Application arguments -->
<meta-data android:name=\"android.app.lib_name\" android:value=\"openrecipes\"/>
<meta-data android:name=\"android.app.qt_sources_resource_id\" android:resource=\"@array/qt_sources\"/>
<meta-data android:name=\"android.app.repository\" android:value=\"default\"/>
<meta-data android:name=\"android.app.qt_libs_resource_id\" android:resource=\"@array/qt_libs\"/>
<meta-data android:name=\"android.app.bundled_libs_resource_id\" android:resource=\"@array/bundled_libs\"/>
<!-- Deploy Qt libs as part of package -->
<meta-data android:name=\"android.app.bundle_local_qt_libs\" android:value=\"1\"/>
<meta-data android:name=\"android.app.bundled_in_lib_resource_id\" android:resource=\"@array/bundled_in_lib\"/>
<meta-data android:name=\"android.app.bundled_in_assets_resource_id\" android:resource=\"@array/bundled_in_assets\"/>
<!-- Run with local libs -->
<meta-data android:name=\"android.app.use_local_qt_libs\" android:value=\"1\"/>
<meta-data android:name=\"android.app.libs_prefix\" android:value=\"/data/local/tmp/qt/\"/>
<meta-data android:name=\"android.app.load_local_libs\" android:value=\"plugins/platforms/android/libqtforandroid.so:plugins/bearer/libqandroidbearer.so:lib/libQt5QuickParticles.so\"/>
<meta-data android:name=\"android.app.load_local_jars\" android:value=\"jar/QtAndroid.jar:jar/QtAndroid-bundled.jar:jar/QtAndroidBearer.jar:jar/QtAndroidBearer-bundled.jar\"/>
<meta-data android:name=\"android.app.static_init_classes\" android:value=\"\"/>
<!-- Messages maps -->
<meta-data android:value=\"@string/ministro_not_found_msg\" android:name=\"android.app.ministro_not_found_msg\"/>
<meta-data android:value=\"@string/ministro_needed_msg\" android:name=\"android.app.ministro_needed_msg\"/>
<meta-data android:value=\"@string/fatal_error_msg\" android:name=\"android.app.fatal_error_msg\"/>
<!-- Messages maps -->
<!-- Splash screen -->
<meta-data android:name=\"android.app.splash_screen_drawable\" android:resource=\"@drawable/splash\"/>
<meta-data android:name=\"android.app.splash_screen_sticky\" android:value=\"true\"/>
<!-- Splash screen -->
<!-- Background running -->
<!-- Warning: changing this value to true may cause unexpected crashes if the
application still try to draw after
\"applicationStateChanged(Qt::ApplicationSuspended)\"
signal is sent! -->
<meta-data android:name=\"android.app.background_running\" android:value=\"false\"/>
<!-- Background running -->
<!-- auto screen scale factor -->
<meta-data android:name=\"android.app.auto_screen_scale_factor\" android:value=\"false\"/>
<!-- auto screen scale factor -->
<!-- extract android style -->
<!-- available android:values :
* full - useful QWidget & Quick Controls 1 apps
* minimal - useful for Quick Controls 2 apps, it is much faster than \"full\"
* none - useful for apps that don\'t use any of the above Qt modules
-->
<meta-data android:name=\"android.app.extract_android_style\" android:value=\"minimal\"/>
<!-- extract android style -->
</activity>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
</application>
<uses-sdk android:minSdkVersion=\"16\" android:targetSdkVersion=\"27\"/>
<supports-screens android:largeScreens=\"true\" android:normalScreens=\"true\" android:anyDensity=\"true\" android:smallScreens=\"true\"/>
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
Remove the comment if you do not require these default features. -->
<!-- %%INSERT_PERMISSIONS -->
<!-- %%INSERT_FEATURES -->
</manifest>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="951.8259"
android:viewportHeight="951.8259">
<group android:translateX="225.91298"
android:translateY="225.91298">
<path
android:pathData="M468.7,160.8L468.7,72.5c0,-11.3 -4.7,-14.7 -10.6,-14.7 -9.7,0 -14.4,25.3 -16.7,54.1a236.3,236.3 0,0 1,7.5 10.5,236.3 236.3,0 0,1 11.8,20.5 236.3,236.3 0,0 1,8.1 18z"
android:strokeLineCap="round"
android:fillAlpha="1"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillColor="#f9f9f9"
android:strokeWidth="1.21636021"
android:strokeLineJoin="miter"
android:strokeAlpha="1"/>
<path
android:pathData="m439.2,391.1l0,42.3c0,4.9 4.7,8.8 10.6,8.8l8.3,0c5.9,0 10.6,-3.9 10.6,-8.8l0,-94.2a236.3,236.3 129.2,0 1,-1 2.8,236.3 236.3,119.1 0,1 -10.3,21.3 236.3,236.3 0,0 1,-12.3 20.1,236.3 236.3,75.9 0,1 -5.9,7.7z"
android:strokeLineCap="round"
android:fillAlpha="1"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillColor="#f9f9f9"
android:strokeWidth="1.21636021"
android:strokeLineJoin="miter"
android:strokeAlpha="1"/>
<path
android:pathData="M250,250m-225,0a225,225 0,1 1,450 0a225,225 0,1 1,-450 0"
android:strokeLineCap="round"
android:fillAlpha="1"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillColor="#ffffff"
android:strokeWidth="0.3589749"
android:strokeLineJoin="miter"
android:strokeAlpha="1"/>
<path
android:pathData="M250,250m-159.9,0a159.9,159.9 0,1 1,319.7 0a159.9,159.9 0,1 1,-319.7 0"
android:strokeLineCap="round"
android:fillAlpha="1"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillColor="#e6e6e6"
android:strokeWidth="0.28859508"
android:strokeLineJoin="miter"
android:strokeAlpha="1"/>
<path
android:pathData="M250,250m-142.7,0a142.7,142.7 0,1 1,285.4 0a142.7,142.7 0,1 1,-285.4 0"
android:strokeLineCap="round"
android:fillAlpha="1"
android:fillType="nonZero"
android:strokeColor="#00000000"
android:fillColor="#f9f9f9"
android:strokeWidth="0.27042723"
android:strokeLineJoin="miter"
android:strokeAlpha="1"/>
</group>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/ic_launcher_background"/>
</shape>
</item>
<item android:drawable="@drawable/ic_launcher_foreground"
android:gravity="center"/>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">OpenRecipes</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splash</item>
<item name="android:colorPrimary">@color/ic_launcher_background</item>
<item name="android:colorPrimaryDark">@color/ic_launcher_background</item>
<item name="android:colorAccent">@color/ic_launcher_background</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FF5722</color>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">OpenRecipes</string>
</resources>
package org.jschwab.recipes;
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Base64;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.IllegalArgumentException;
public class Helpers {
public static String readImage(Uri uri, Context context) {
try {
InputStream stream = context.getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(stream);
int newWidth = (int) ((double)bitmap.getWidth() * 120. / (double)bitmap.getHeight());
try {
bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, 120, false);
} catch (IllegalArgumentException e) {
return "";
}
stream.close();
ByteArrayOutputStream data = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, data);
String begin = "data:image/png;base64,";
return begin + Base64.encodeToString(data.toByteArray(), Base64.DEFAULT);
} catch (FileNotFoundException e) {
return "";
} catch (IOException e) {
return "";
}
}
}
cd `dirname "${BASH_SOURCE[0]}"`
make distclean
export OPENRECIPES_ANDROID_SYSROOT=`pwd`/androidlibs/arm
export ANDROID_NDK_PLATFORM=android-27
~/Qt/5.11.1/android_armv7/bin/qmake
make clean
make -j5
mkdir client/android_arm
make install INSTALL_ROOT=android_arm
cd client
export TERM=xterm-color
~/Qt/5.11.1/android_armv7/bin/androiddeployqt --output android_arm --gradle --input android-libopenrecipes.so-deployment-settings.json --release
cd `dirname "${BASH_SOURCE[0]}"`
make distclean
export OPENRECIPES_ANDROID_SYSROOT=`pwd`/androidlibs/x86
export ANDROID_NDK_PLATFORM=android-27
~/Qt/5.11.1/android_x86/bin/qmake
make clean
make -j5
mkdir client/android_x86
make install INSTALL_ROOT=android_x86
cd client
export TERM=xterm-color
~/Qt/5.11.1/android_x86/bin/androiddeployqt --output android_x86 --gradle --input android-libopenrecipes.so-deployment-settings.json --release
cd `dirname "${BASH_SOURCE[0]}"`
make distclean
~/Qt/5.10.0/gcc_64/bin/qmake
make clean
make -j5
make check
#!/bin/bash
set -o xtrace
relScriptPath=`dirname "${BASH_SOURCE[0]}"`
scriptPath=`realpath $relScriptPath`
libsPath="${scriptPath}/androidlibs"
LIB_SODIUM_DIR="libsodium-1.0.16"
LIB_SODIUM_TAR="libsodium-1.0.16.tar.gz"
TARGET_ARM="arm-linux-androideabi"
TARGET_x86="i686-linux-android"
tar -xf $LIB_SODIUM_TAR
cd $LIB_SODIUM_DIR
export CFLAGS="-D_FORTIFY_SOURCE=2"
oldPATH=$PATH
export PATH=$oldPATH:${scriptPath}/android-ndk-toolchain/arm/bin
./configure --host $TARGET_ARM --prefix ${libsPath}/arm
make -j5 V=1
make install
make clean
export PATH=$oldPATH:${scriptPath}/android-ndk-toolchain/x86/bin
./configure --host $TARGET_x86 --prefix ${libsPath}/x86
make -j5 V=1
make install
cd lib
qmake -tp vc lib.pro "CONFIG+=windeployqt"
cd ..\client
qmake -tp vc client.pro "CONFIG+=windeployqt"
cd ..
TEMPLATE = app
TARGET = openrecipes
QT += qml quick quickcontrols2 sql svg widgets xml
include( ../linking.pri )
include( ../common.pri )
HEADERS += src/SqlBackend.h \
src/Backend.h \
src/Ingredient.h \
src/Recipe.h \
src/PRandom.h \
src/SynchronizeAsync.h \
src/SendSyncKeyAsync.h \
src/RecvSyncKeyAsync.h \
src/SecureClientConnection.h \
src/DataStructs.h \
src/EncryptedItem.h \
src/Globals.h \
src/RecipeTcpServer.h \
src/RecipeTcpClient.h
SOURCES += src/main.cpp \
src/SqlBackend.cpp \
src/Backend.cpp \
src/Ingredient.cpp \
src/DataStructs.cpp \
src/Recipe.cpp \
src/PRandom.cpp \
src/SynchronizeAsync.cpp \
src/SendSyncKeyAsync.cpp \
src/RecvSyncKeyAsync.cpp \
src/SecureClientConnection.cpp \
src/EncryptedItem.cpp \
src/Globals.cpp \
src/RecipeTcpServer.cpp \
src/RecipeTcpClient.cpp
RESOURCES += client.qrc
QMAKE_SUBSTITUTES += \
../android-sources/AndroidManifest.xml.in
TRANSLATIONS += intl/client_de.ts
lupdate_only {SOURCES += qml/*.qml}
android {
#There are more translation files available there, but this one seems to suffice
QMAKE_POST_LINK = $$QMAKE_MKDIR $$shell_path($$PWD/../android-sources/assets/translations) && $$QMAKE_COPY $$shell_path($$[QT_INSTALL_TRANSLATIONS]/qt_de.qm) $$shell_path($$PWD/../android-sources/assets/translations)
}
qtPrepareTool(LRELEASE, lrelease)
system($$LRELEASE $$_PRO_FILE_)|error("Can't run lrelease")
QMAKE_DISTCLEAN += $$PWD/intl/client_*.qm
unix {
system($$QMAKE_COPY $$PWD/img/icon.svg $$PWD/img/openrecipes.svg)
QMAKE_DISTCLEAN += $$PWD/img/openrecipes.svg
}
target.path = /usr/bin
icon.path = /usr/share/pixmaps
icon.files = $$PWD/img/openrecipes.svg
desktop.path = /usr/share/applications
desktop.files = $$PWD/openrecipes.desktop
INSTALLS += target
!android: INSTALLS += icon desktop
lessThan(QT_MINOR_VERSION, 10): warning("You seem to use a Qt version prior to 5.10.0. The client will build with this version, but NOT run.")
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
<file alias="qtquickcontrols2.conf">qml/qtquickcontrols2.conf</file>
<file alias="+android/qtquickcontrols2.conf">qml/+android/qtquickcontrols2.conf</file>
<file>qml/BigLabel.qml</file>
<file>qml/DoubleSpinBox.qml</file>
<file>qml/MainWindowDesktop.qml</file>
<file>qml/MainWindowMobile.qml</file>
<file>qml/MediumLabel.qml</file>
<file>qml/ModalDialog.qml</file>
<file>qml/OpenImageDialog.qml</file>
<file>qml/RecipeEditView.qml</file>
<file>qml/RecipeView.qml</file>
<file>qml/RecipesListView.qml</file>
<file>qml/RecipesSearchView.qml</file>
<file>qml/RoundedImage.qml</file>
<file>qml/SettingsView.qml</file>
<file>qml/UnsupportedVersionWindow.qml</file>
<file>img/fallback-icons/configure.svg</file>
<file>img/fallback-icons/document-edit.svg</file>
<file>img/fallback-icons/document-new.svg</file>
<file>img/fallback-icons/document-open.svg</file>
<file>img/fallback-icons/document-share.svg</file>
<file>img/fallback-icons/download.svg</file>
<file>img/fallback-icons/edit-clear.svg</file>
<file>img/fallback-icons/edit-delete.svg</file>
<file>img/fallback-icons/list-add.svg</file>
<file>img/fallback-icons/view-refresh.svg</file>
<file>img/icon_plain.svg</file>
<file>img/icon.svg</file>
<file>intl/client_de.qm</file>
</qresource>
</RCC>
#!/bin/bash
echo "FIXME: Paths not correct anymore"
exit 1
cd `dirname "${BASH_SOURCE[0]}"`
W=(48 72 96 144 192)
DPINAME=("mdpi" "hdpi" "xhdpi" "xxhdpi" "xxxhdpi")
for ((ii=0;ii<5;ii++));
do
echo "Processing icon.svg for ${DPINAME[$ii]}@${W[$ii]} px"
suffix=${DPINAME[$ii]}
resdir="android-sources/res"
dirname=$resdir/drawable-${DPINAME[$ii]}
fname="$dirname"/icon.png
inkscape -z -f=img/icon.svg --export-png="$fname" \
-h=${W[$ii]}
done
openrecipes (0.1.0-1) unstable; urgency=low