diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a1d9d6f..d020638 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ target_compile_options(distromatic PUBLIC -O2 -g -Wall -std=gnu11 -pedantic ${RP # -fno-toplevel-reorder add_executable(distroquery + DistroqueryAPI.cpp distroquery.cpp functions.c headerlist.c @@ -94,6 +95,8 @@ target_include_directories(distroquery PUBLIC ${LIBUNWIND_INCLUDE_DIRS} ) +target_compile_options(distroquery PUBLIC -O2 -g -Wall $<$:-std=c++14> -pedantic ${RPM_CFLAGS_OTHER}) + install( TARGETS distromatic DESTINATION ${CMAKE_INSTALL_PREFIX}/bin diff --git a/src/distroquery.cpp b/src/distroquery.cpp index 22fcd73..1371496 100644 --- a/src/distroquery.cpp +++ b/src/distroquery.cpp @@ -17,7 +17,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ -#include +#include "distroquery.hpp" +#include "DistroqueryAPI.hpp" #include #include @@ -217,23 +218,23 @@ sqlite3* openRepositoryDatabase(struct configTag* ct, char* arch) { } void attachCtDatabases(struct configTag* ct, sqlite3 *db, char* arch) { - char dbname[PATH_MAX]; + string dbname; + string sql; int i=0; - char sql[PATH_MAX]; char *errmsg; while (ct->repository[i]) { - if (arch) { - snprintf(dbname, PATH_MAX, "%s%s-%s.db", ct->repository[i]->repository_dir, ct->repository[i]->tag, arch); - snprintf(sql, PATH_MAX, "ATTACH DATABASE '%s' as '%s_%s'", dbname, ct->repository[i]->tag, arch); - if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { - fprintf(stderr, "ERROR: unable to exec statement for %s: %s\n", sql, errmsg); + if (arch) { + dbname = string(ct->repository[i]->repository_dir) + ct->repository[i]->tag + "-" + arch + ".db"; + sql = "ATTACH DATABASE '" + dbname + "' as '" + ct->repository[i]->tag + "_" + arch + "'"; + if (sqlite3_exec(db, sql.c_str(), NULL, NULL, &errmsg)) { + cerr << "ERROR: unable to exec statement for " << sql << ": " << errmsg << endl; } } else { - snprintf(dbname, PATH_MAX, "%s%s-sources.db", ct->repository[i]->repository_dir, ct->repository[i]->tag); - snprintf(sql, PATH_MAX, "ATTACH DATABASE '%s' as '%s_sources'", dbname, ct->repository[i]->tag); - if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { - fprintf(stderr, "ERROR: unable to exec statement for %s: %s\n", sql, errmsg); + dbname = string(ct->repository[i]->repository_dir) + ct->repository[i]->tag + "-sources.db"; + sql = "ATTACH DATABASE '" + dbname + "' as '" + ct->repository[i]->tag + "_sources'"; + if (sqlite3_exec(db, sql.c_str(), NULL, NULL, &errmsg)) { + cerr << "ERROR: unable to exec statement for " << sql << ": " << errmsg << endl; } } i++; @@ -241,22 +242,22 @@ void attachCtDatabases(struct configTag* ct, sqlite3 *db, char* arch) { } void attachRepositoryDatabases(struct configTag* ct, sqlite3 *db, char* arch, int source) { - char dbname[PATH_MAX]; - char sql[PATH_MAX]; - char *errmsg; + string dbname; + string sql; + char *errmsg; - snprintf(dbname, PATH_MAX, "%s%s-%s.db", ct->repository_dir, ct->tag, arch); - snprintf(sql, PATH_MAX, "ATTACH DATABASE '%s' as '%s_%s'", dbname, ct->tag, arch); - if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { - fprintf(stderr, "ERROR: unable to exec statement for %s: %s\n", sql, errmsg); - } - if (source) { - snprintf(dbname, PATH_MAX, "%s%s-sources.db", ct->repository_dir, ct->tag); - snprintf(sql, PATH_MAX, "ATTACH DATABASE '%s' as '%s_sources'", dbname, ct->tag); - if (sqlite3_exec(db, sql, NULL, NULL, &errmsg)) { - fprintf(stderr, "ERROR: unable to exec statement for %s: %s\n", sql, errmsg); - } - } + dbname = string(ct->repository_dir) + ct->tag + "-" + arch + ".db"; + sql = "ATTACH DATABASE '" + dbname + "' as '" + ct->tag + "_" + arch; + if (sqlite3_exec(db, sql.c_str(), NULL, NULL, &errmsg)) { + cerr << "ERROR: unable to exec statement for " << sql << ": " << errmsg << endl; + } + if (source) { + dbname = string(ct->repository_dir) + ct->tag + "-sources.db"; + sql = "ATTACH DATABASE '" + dbname + "' as '" + ct->tag + "_sources'"; + if (sqlite3_exec(db, sql.c_str(), NULL, NULL, &errmsg)) { + cerr << "ERROR: unable to exec statement for " << sql << ":: " << errmsg << endl; + } + } } void detachRepositoryDatabases(struct configTag* ct, sqlite3 *db, char* arch, int source) { @@ -363,11 +364,11 @@ void printInputForm() { } int findFileIdFromPath(sqlite3 *db, char** path) { - int frompos = 1, topos; + size_t frompos = 1, topos; int parent = -1; char* pt; char buffer[PATH_MAX]; - char sql[PATH_MAX]; + string sql; char* linkpath = (char*)calloc(strlen(*path),1); sqlite3_stmt* stmt1; @@ -378,9 +379,8 @@ int findFileIdFromPath(sqlite3 *db, char** path) { if (pt) topos = pt - *path; else topos = strlen(*path); strncpy(buffer, *path + frompos, topos - frompos); buffer[topos-frompos]=0; - snprintf(sql, PATH_MAX, "SELECT id FROM files WHERE parent=%d" - " AND name='%s'", parent, buffer); - if (sqlite3_prepare_v2(db, sql, strlen(sql), &stmt1, NULL) == SQLITE_OK && sqlite3_step(stmt1) == SQLITE_ROW) { + sql = "SELECT id FROM files WHERE parent=" + to_string(parent) + " AND name='" + buffer + "'"; + if (sqlite3_prepare_v2(db, sql.c_str(), sql.length(), &stmt1, NULL) == SQLITE_OK && sqlite3_step(stmt1) == SQLITE_ROW) { parent = sqlite3_column_int(stmt1,0); sqlite3_finalize(stmt1); strncat(linkpath, "/", strlen(*path) - strlen(linkpath)); @@ -490,28 +490,28 @@ int packageVerCmp(int e1, const char* v1, const char* r1, int e2, const char* v2 void printQueryResponse() { - int a, i, j, k, numresults = 0, otherresults = 0, localresults = 0, localprovidesresults = 0, localsourceresults = 0; + int a, j, k, numresults = 0, otherresults = 0, localresults = 0, localprovidesresults = 0, localsourceresults = 0; char dbname[PATH_MAX]; sqlite3 *dbf; sqlite3_stmt *statement, *stmt1; char sql[PATH_MAX]; char buffer[PATH_MAX]; - char queryenc[PATH_MAX]; + string queryenc; if (!reply_plain) printf("<%s>arch[a]; a++) { if (find_query_arch(query_repositories[i]->arch[a]) >= 0) { if (!query_repositories[i]->db[a]) { snprintf(dbname, PATH_MAX, "%s%s-%s.db", query_repositories[i]->repository_dir, query_repositories[i]->tag, query_repositories[i]->arch[a]); if (sqlite3_open_v2(dbname, (sqlite3**)&query_repositories[i]->db[a], SQLITE_OPEN_READONLY, NULL)) { - if (query_repositories[i]->db) sqlite3_close((sqlite3*)query_repositories[i]->db[a]); + sqlite3_close((sqlite3*)query_repositories[i]->db[a]); query_repositories[i]->db[a] = NULL; fprintf(stderr, "ERROR: unable to open sqlite3 db %s; ignoring.\n", dbname); } @@ -533,7 +533,8 @@ void printQueryResponse() { "groupdescr LIKE 'Graphical Desktop/%%' DESC, groupdescr LIKE 'Applications/%%' DESC, " "groupdescr LIKE 'Development/%%' ASC, groupdescr LIKE 'Documentation%%' ASC, groupdescr LIKE 'System/Libraries%%' ASC, " "name LIKE '%%-devel' ASC, name LIKE '%%-debug' ASC " - "LIMIT %d OFFSET %d", queryenc, queryenc, queryenc, queryenc, queryenc, queryenc, queryenc, query_limit, query_offset); + "LIMIT %d OFFSET %d", queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), + queryenc.c_str(), queryenc.c_str(), query_limit, query_offset); if (sqlite3_prepare_v2((sqlite3*)query_repositories[i]->db[a], sql, strlen(sql), &statement, NULL) == SQLITE_OK) { while (sqlite3_step(statement) == SQLITE_ROW) { numresults++; @@ -630,7 +631,8 @@ void printQueryResponse() { "(provides.id_package=packages.id AND provided.id=provides.id_provided) " "AND provided.name LIKE '%%%s%%' " "ORDER BY provided.name = '%s' DESC, provided.name LIKE '%s%%' DESC, provided.name LIKE '%%%s%%' DESC " - "LIMIT %d OFFSET %d", queryenc, queryenc, queryenc, queryenc, query_limit, query_offset); + "LIMIT %d OFFSET %d", queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), + query_limit, query_offset); if (sqlite3_prepare_v2((sqlite3*)query_repositories[i]->db[a], sql, strlen(sql), &statement, NULL) == SQLITE_OK) { while (sqlite3_step(statement) == SQLITE_ROW) { numresults++; @@ -685,7 +687,8 @@ void printQueryResponse() { "packages_files_rel.id_file = files.id " "ORDER BY files.name = '%s' DESC, files.name LIKE '%s%%' DESC, " "files.name LIKE '%%%s%%' DESC LIMIT %d OFFSET %d", - queryenc, queryenc, queryenc, queryenc, query_limit, query_offset); + queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), + query_limit, query_offset); if (sqlite3_prepare_v2(dbf, sql, strlen(sql), &stmt1, NULL) == SQLITE_OK) { while (sqlite3_step(stmt1) == SQLITE_ROW) { numresults++; @@ -734,8 +737,9 @@ void printQueryResponse() { snprintf(sql, PATH_MAX, "SELECT * FROM sources WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%' OR version LIKE '%%%s%%' " "ORDER BY name = '%s' DESC, name LIKE '%s%%' DESC, name LIKE '%%%s%%' DESC LIMIT %d OFFSET %d", - queryenc, queryenc, queryenc, queryenc, queryenc, queryenc, queryenc, query_limit, query_offset); - for (i = 0; query_repositories[i] != NULL; i++) { + queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), queryenc.c_str(), + queryenc.c_str(), query_limit, query_offset); + for (auto i = 0; query_repositories[i] != NULL; i++) { if (!query_repositories[i]->db[ARCHS_MAX]) { snprintf(dbname, PATH_MAX, "%s%s-sources.db", query_repositories[i]->repository_dir, query_repositories[i]->tag); if (sqlite3_open_v2(dbname, (sqlite3**)&query_repositories[i]->db[ARCHS_MAX], SQLITE_OPEN_READONLY, NULL)) { @@ -814,7 +818,7 @@ void printQueryResponse() { } else a=j+9; /* a = number of page links displayed */ if (a > 1) { printf(" [ "); - for (i = j; i <= a; i++) { + for (auto i = j; i <= a; i++) { if (i != k) printf("", query_next, query_limit, query_limit * (i-1)); printf("%d", i); @@ -829,7 +833,7 @@ void printQueryResponse() { printf("]]>"); } - for (i = 0; query_repositories[i] != NULL; i++) { + for (auto i = 0; query_repositories[i] != NULL; i++) { for (a = 0; a <= ARCHS_MAX && query_repositories[i]->arch[a]; a++) { if (query_repositories[i]->db[a]) { sqlite3_close((sqlite3*)query_repositories[i]->db[a]); @@ -1608,7 +1612,7 @@ void parse_request_variables(char *data) { int main(int argc, char *argv[]) { - char *data; + char *path_info, *query_string; int responsed = 0; // install backtrace handler @@ -1620,11 +1624,22 @@ main(int argc, char *argv[]) exit(1); } - data = getenv("QUERY_STRING"); - if (data && strlen(data)) { - parse_request_variables(data); + path_info = getenv("PATH_INFO"); + query_string = getenv("QUERY_STRING"); + + if (strncmp(path_info, "/api/v1/", strlen(API_PREFIX)) == 0) { + DistroqueryAPI api; + api.getApiResponse(&path_info[strlen(API_PREFIX)]); + } else if (strlen(path_info) > 0) { + cout << "Content-Type: text/html;charset=utf-8" << endl; + cout << "Status: 400 Bad request" << endl << endl; + cout << "ERROR: invalid path: " << path_info; + exit(1); } + if (query_string && strlen(query_string)) { + parse_request_variables(query_string); + } if (!reply_plain) printf("Content-Type: text/xml;charset=utf-8\n\n");