More security and less unexpected behaviour. #8

Merged
andrewlalis merged 7 commits from development into master 2018-03-30 14:20:54 +00:00
12 changed files with 105 additions and 39 deletions
Showing only changes of commit 35982cd514 - Show all commits

View File

@ -195,6 +195,7 @@ void NewRecipeDialog::on_newUnitButton_clicked(){
QMessageBox::critical(this, "Error", "Unable to store new unit.");
} else {
this->populateUnitsBox();
ui->unitComboBox->setCurrentText(QString::fromStdString(u.getName()));
}
}
}

View File

@ -6,6 +6,8 @@
#include "model/database/recipedatabase.h"
#include "utils/fileutils.h"
void test(RecipeDatabase *recipeDB);
int main(int argc, char *argv[])
{
RecipeDatabase recipeDB(QString(FileUtils::appDataPath+"recipes.db").toStdString());
@ -14,6 +16,18 @@ int main(int argc, char *argv[])
w.show();
//TESTING CODE
test(&recipeDB);
//END TESTING CODE.
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
a.exec();
recipeDB.closeConnection();
return 0;
}
void test(RecipeDatabase *recipeDB){
vector<RecipeIngredient> ri;
ri.push_back(RecipeIngredient("flour", "grains", 3.0f, UnitOfMeasure("cup", "cups", "c", UnitOfMeasure::VOLUME, 1.0), ""));
ri.push_back(RecipeIngredient("baking powder", "additives", 1.0f, UnitOfMeasure("teaspoon", "teaspoons", "tsp", UnitOfMeasure::VOLUME, 1.0), ""));
@ -29,12 +43,21 @@ int main(int argc, char *argv[])
QTime(0, 25),
10.0f);
bool success = recipeDB.storeRecipe(rec);
bool success = recipeDB->storeRecipe(rec);
printf("Storage successful: %d\n", success);
w.loadFromRecipe(recipeDB.retrieveRandomRecipe());
vector<string> foodGroups = recipeDB->retrieveAllFoodGroups();
printf("Food Groups:\n");
for (string s : foodGroups){
printf("\t%s\n", s.c_str());
}
//Get food groups from recipe.
Recipe r = recipeDB->retrieveRecipe("Pannenkoeken");
vector<string> foodGroupsR = r.getFoodGroups();
printf("Pannenkoeken Food Groups:\n");
for (string s : foodGroupsR){
printf("\t%s\n", s.c_str());
}
a.exec();
recipeDB.closeConnection();
return 0;
}

View File

@ -88,7 +88,7 @@ int RecipeDatabase::storeIngredient(Ingredient ingredient){
return -1;
}
} else {
return std::stoi(t.valueAt(0, 0));
return std::stoi(t.at(0, 0));
}
}
@ -162,12 +162,21 @@ Recipe RecipeDatabase::retrieveRandomRecipe(){
vector<Recipe> RecipeDatabase::retrieveAllRecipes(){
ResultTable t = this->selectFrom("recipe", "name", "ORDER BY name");
vector<Recipe> recipes;
for (unsigned int row = 0; row < t.rowCount(); row++){
recipes.push_back(this->retrieveRecipe(t.valueAt(row, 0)));
for (TableRow row : t.rows()){
recipes.push_back(this->retrieveRecipe(row.at(0)));
}
return recipes;
}
vector<string> RecipeDatabase::retrieveAllFoodGroups(){
ResultTable t = this->executeSQL("SELECT DISTINCT foodGroup FROM ingredient ORDER BY foodGroup;");
vector<string> foodGroups;
for (TableRow row : t.rows()){
foodGroups.push_back(row.at(0));
}
return foodGroups;
}
vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId){
ResultTable t = this->executeSQL("SELECT ingredient.name, ingredient.foodGroup, "//0, 1
"recipeIngredient.quantity, recipeIngredient.unitName, recipeIngredient.comment,"//2, 3, 4
@ -179,33 +188,33 @@ vector<RecipeIngredient> RecipeDatabase::retrieveRecipeIngredients(int recipeId)
"ON recipeIngredient.unitName = unitOfMeasure.name "
"WHERE recipeIngredient.recipeId = "+std::to_string(recipeId)+";");
vector<RecipeIngredient> ings;
for (unsigned int row = 0; row < t.rowCount(); row++){
RecipeIngredient r(t.valueAt(row, 0),
t.valueAt(row, 1),
std::stof(t.valueAt(row, 2)),
UnitOfMeasure(t.valueAt(row, 5), t.valueAt(row, 6), t.valueAt(row, 7), std::stoi(t.valueAt(row, 8)), std::stod(t.valueAt(row, 9))),
t.valueAt(row, 4));
for (TableRow row : t.rows()){
RecipeIngredient r(row.at(0),
row.at(1),
std::stof(row.at(2)),
UnitOfMeasure(row.at(5), row.at(6), row.at(7), std::stoi(row.at(8)), std::stod(row.at(9))),
row.at(4));
ings.push_back(r);
}
return ings;
}
vector<Ingredient> RecipeDatabase::retrieveAllIngredients(){
ResultTable t = this->selectFrom("ingredient", "*", "ORDER BY name");
ResultTable t = this->selectFrom("ingredient", "name, foodGroup", "ORDER BY name");
vector<Ingredient> ings;
for (unsigned int row = 0; row < t.rowCount(); row++){
Ingredient i(t.valueAt(row, 2), t.valueAt(row, 1));
for (TableRow row : t.rows()){
Ingredient i(row.at(0), row.at(1));
ings.push_back(i);
}
return ings;
}
vector<UnitOfMeasure> RecipeDatabase::retrieveAllUnitsOfMeasure(){
ResultTable t = this->selectFrom("unitOfMeasure", "*", "ORDER BY name");
ResultTable t = this->selectFrom("unitOfMeasure", "name, plural, abbreviation, type, metricCoefficient", "ORDER BY name");
vector<UnitOfMeasure> units;
if (!t.isEmpty()){
for (unsigned int row = 0; row < t.rowCount(); row++){
UnitOfMeasure u(t.valueAt(row, 0), t.valueAt(row, 1), t.valueAt(row, 2), std::stoi(t.valueAt(row, 3)), std::stod(t.valueAt(row, 4)));
for (TableRow row : t.rows()){
UnitOfMeasure u(row.at(0), row.at(1), row.at(2), std::stoi(row.at(3)), std::stod(row.at(4)));
units.push_back(u);
}
}
@ -213,11 +222,11 @@ vector<UnitOfMeasure> RecipeDatabase::retrieveAllUnitsOfMeasure(){
}
vector<RecipeTag> RecipeDatabase::retrieveTags(int recipeId){
ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId));
ResultTable t = this->selectFrom("recipeTag", "tagName", "WHERE recipeId="+std::to_string(recipeId)+" ORDER BY tagName");
vector<RecipeTag> tags;
if (!t.isEmpty()){
for (unsigned int row = 0; row < t.rowCount(); row++){
RecipeTag tag(t.valueAt(row, 0));
for (TableRow row : t.rows()){
RecipeTag tag(row.at(0));
tags.push_back(tag);
}
}
@ -228,8 +237,8 @@ vector<RecipeTag> RecipeDatabase::retrieveAllTags(){
ResultTable t = this->selectFrom("recipeTag", "tagName", "ORDER BY tagName");
vector<RecipeTag> tags;
if (!t.isEmpty()){
for (unsigned int row = 0; row < t.rowCount(); row++){
RecipeTag tag(t.valueAt(row, 0));
for (TableRow row : t.rows()){
RecipeTag tag(row.at(0));
tags.push_back(tag);
}
}
@ -241,7 +250,7 @@ bool RecipeDatabase::deleteRecipe(string name){
if (t.rowCount() != 1){
return false;
}
string recipeId = t.valueAt(0, 0);
string recipeId = t.at(0, 0);
return this->deleteRecipe(std::stoi(recipeId));
}
@ -257,6 +266,8 @@ bool RecipeDatabase::deleteRecipe(int recipeId){
bool recipeDeleted = this->deleteFrom("recipe", "WHERE recipeId="+idString);
bool instructionDeleted = FileUtils::deleteInstruction(recipeId);
bool imageDeleted = FileUtils::deleteImage(recipeId);
Q_UNUSED(instructionDeleted);
Q_UNUSED(imageDeleted);
if (tagsDeleted && recipeIngredientDeleted && recipeDeleted){
this->executeSQL("COMMIT;");
return true;
@ -334,14 +345,15 @@ void RecipeDatabase::ensureTablesExist(){
this->executeSQL("COMMIT;");
}
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int row){
Recipe RecipeDatabase::readFromResultTable(ResultTable t, int tRow){
Recipe r;
int id = std::stoi(t.valueAt(row, 0));
r.setName(t.valueAt(row, 1));
r.setCreatedDate(QDate::fromString(QString::fromStdString(t.valueAt(row, 2))));
r.setPrepTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 3))));
r.setCookTime(QTime::fromString(QString::fromStdString(t.valueAt(row, 4))));
r.setServings(std::stof(t.valueAt(row, 5)));
TableRow row = t.rows().at(tRow);
int id = std::stoi(row.at(0));
r.setName(row.at(1));
r.setCreatedDate(QDate::fromString(QString::fromStdString(row.at(2))));
r.setPrepTime(QTime::fromString(QString::fromStdString(row.at(3))));
r.setCookTime(QTime::fromString(QString::fromStdString(row.at(4))));
r.setServings(std::stof(row.at(5)));
r.setInstruction(FileUtils::loadInstruction(id));
r.setImage(FileUtils::loadImage(id));
r.setIngredients(this->retrieveRecipeIngredients(id));

View File

@ -34,6 +34,7 @@ class RecipeDatabase : public Database
Recipe retrieveRecipe(string name);
Recipe retrieveRandomRecipe();
vector<Recipe> retrieveAllRecipes();
vector<string> retrieveAllFoodGroups();
vector<RecipeIngredient> retrieveRecipeIngredients(int recipeId);
vector<Ingredient> retrieveAllIngredients();
vector<UnitOfMeasure> retrieveAllUnitsOfMeasure();

View File

@ -47,7 +47,7 @@ bool ResultTable::isEmpty(){
return this->values.empty();
}
string ResultTable::valueAt(unsigned int row, unsigned int col){
string ResultTable::at(unsigned int row, unsigned int col){
if (isIndexValid(row, col)){
return this->values[row][col];
} else {
@ -78,6 +78,10 @@ unsigned int ResultTable::rowCount(){
return this->values.size();
}
vector<vector<string> > ResultTable::rows(){
return this->values;
}
string ResultTable::convertToString(sqlite3_value *val){
const unsigned char* raw_text = sqlite3_value_text(val);
if (raw_text == 0){

View File

@ -12,6 +12,8 @@ using namespace std;
* @brief The ResultTable class is an object that contains the results of an SQL query, in string form.
*/
typedef vector<string> TableRow;
class ResultTable
{
public:
@ -28,11 +30,12 @@ class ResultTable
void printData();
bool isEmpty();
string valueAt(unsigned int row, unsigned int col);
string at(unsigned int row, unsigned int col);
int getReturnCode();
string getOriginalQuery();
unsigned int columnCount();
unsigned int rowCount();
vector<vector<string>> rows();
private:
vector<vector<string>> values;
int queryCode;

View File

@ -24,6 +24,16 @@ vector<RecipeIngredient> Recipe::getIngredients() const{
return this->ingredients;
}
vector<string> Recipe::getFoodGroups() const{
vector<string> foodGroups;
for (RecipeIngredient ri : this->ingredients){
if (find(foodGroups.begin(), foodGroups.end(), ri.getFoodGroup()) == foodGroups.end()){
foodGroups.push_back(ri.getFoodGroup());
}
}
return foodGroups;
}
Instruction Recipe::getInstruction() const{
return this->instruction;
}

View File

@ -6,6 +6,7 @@
#include <QDate>
#include <QTime>
#include <QImage>
#include <algorithm>
#include "model/recipe/ingredients/recipeingredient.h"
#include "model/recipe/instruction.h"
@ -38,6 +39,7 @@ public:
//Getters
string getName() const;
vector<RecipeIngredient> getIngredients() const;
vector<string> getFoodGroups() const;
Instruction getInstruction() const;
QImage getImage() const;
vector<RecipeTag> getTags() const;

View File

@ -72,8 +72,8 @@ void RecipeTableModel::setRecipes(vector<Recipe> recipes){
endInsertRows();
}
Recipe RecipeTableModel::getRecipeAt(int index){
if (index < 0 || index >= this->recipes.size()){
Recipe RecipeTableModel::getRecipeAt(unsigned int index){
if (index >= this->recipes.size()){
return Recipe();
}
return this->recipes[index];

View File

@ -20,7 +20,7 @@ class RecipeTableModel : public QAbstractTableModel
//Normal methods.
void setRecipes(vector<Recipe> recipes);
Recipe getRecipeAt(int index);
Recipe getRecipeAt(unsigned int index);
void clear();
private:
vector<Recipe> recipes;

View File

@ -29,4 +29,13 @@ std::string toString(float val){
return s;
}
void printVector(std::vector<std::string> &vect){
std::printf("Vector of %ld elements:\n", vect.size());
int c = 0;
for (std::string s : vect){
std::printf("\t[%d] = %s\n", c, s.c_str());
c++;
}
}
}

View File

@ -2,6 +2,7 @@
#define STRINGUTILS_H
#include <string>
#include <vector>
#include <cmath>
namespace StringUtils{