From 07458b8141b65a1e95a1cb323b99e1c577bacd5c Mon Sep 17 00:00:00 2001
From: Alexey Makhalov <amakhalov@vmware.com>
Date: Fri, 11 Nov 2016 04:22:35 +0000
Subject: [PATCH 4/6] Mapping supports vendor:product combination

---
 src/core.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 src/core.h |  4 ++--
 src/main.c | 17 ++++++++++++---
 3 files changed, 71 insertions(+), 23 deletions(-)

diff --git a/src/core.c b/src/core.c
index 8f809a3..d03f856 100644
--- a/src/core.c
+++ b/src/core.c
@@ -63,7 +63,11 @@ struct CveDB {
         sqlite3 *db;
         sqlite3_stmt *insert;
         sqlite3_stmt *insert_product;
-        sqlite3_stmt *search_product;
+	/*
+	 * index 0 - search by product
+	 * index 1 - search by product and vendor
+	 */
+        sqlite3_stmt *search_product[2];
         sqlite3_stmt *get_cve;
 };
 
@@ -148,32 +152,39 @@ struct cve_entry_t *cve_db_get_cve(CveDB *self, char *id)
         return t;
 }
 
-GList *cve_db_get_issues_frac_compare(CveDB *self, char *product, char *version, GList *in)
+GList *cve_db_get_issues_frac_compare(CveDB *self, char *vendor, char *product, char *version, GList *in)
 {
         int rc = 0;
         GList *list = in;
         int ret = 0;
+	int idx = vendor ? 1 : 0;
 
         if (!self || !self->db) {
                 return NULL;
         }
 
-        sqlite3_reset(self->search_product);
+        sqlite3_reset(self->search_product[idx]);
 
-        if (sqlite3_bind_text(self->search_product, 1, product, -1, SQLITE_STATIC) != SQLITE_OK) {
+        if (sqlite3_bind_text(self->search_product[idx], 1, product, -1, SQLITE_STATIC) != SQLITE_OK) {
                 fprintf(stderr, "cve_db_get_issues_frac_compare(): %s\n", sqlite3_errmsg(self->db));
                 return NULL;
         }
 
-        while ((rc = sqlite3_step(self->search_product)) == SQLITE_ROW) {
-                if ((const char *)sqlite3_column_text(self->search_product, 1) == NULL) /*skip over (null) product*/
+	if (idx)
+        	if (sqlite3_bind_text(self->search_product[idx], 2, vendor, -1, SQLITE_STATIC) != SQLITE_OK) {
+                	fprintf(stderr, "cve_db_get_issues_frac_compare(): %s\n", sqlite3_errmsg(self->db));
+                	return NULL;
+        	}
+
+        while ((rc = sqlite3_step(self->search_product[idx])) == SQLITE_ROW) {
+                if ((const char *)sqlite3_column_text(self->search_product[idx], 1) == NULL) /*skip over (null) product*/
                         continue;
-                if ((const char *)sqlite3_column_text(self->search_product, 2) == NULL) /*skip over (null) version*/
+                if ((const char *)sqlite3_column_text(self->search_product[idx], 2) == NULL) /*skip over (null) version*/
                         continue;
 
-                ret = strverscmp(version, (const char *)sqlite3_column_text(self->search_product, 2));
+                ret = strverscmp(version, (const char *)sqlite3_column_text(self->search_product[idx], 2));
                 if (ret <= 0) { /* our version <= NVD version */
-                        list = g_list_append(list, g_strdup((const char*)sqlite3_column_text(self->search_product, 0)));
+                        list = g_list_append(list, g_strdup((const char*)sqlite3_column_text(self->search_product[idx], 0)));
                 }
         }
 
@@ -187,30 +198,38 @@ GList *cve_db_get_issues_frac_compare(CveDB *self, char *product, char *version,
         return list;
 }
 
-GList *cve_db_get_issues(CveDB *self,  char *product, char *version, GList *in)
+GList *cve_db_get_issues(CveDB *self, char *vendor, char *product, char *version, GList *in)
 {
         int rc = 0;
         GList *list = in;
+	int idx = vendor ? 1 : 0;
 
         if (!self || !self->db) {
                 return NULL;
         }
 
-        sqlite3_reset(self->search_product);
+        sqlite3_reset(self->search_product[idx]);
 
         /* Product */
-        if (sqlite3_bind_text(self->search_product, 1, product, -1, SQLITE_STATIC) != SQLITE_OK) {
+        if (sqlite3_bind_text(self->search_product[idx], 1, product, -1, SQLITE_STATIC) != SQLITE_OK) {
                 fprintf(stderr, "cve_db_get_issues(): %s\n", sqlite3_errmsg(self->db));
                 goto bail;
         }
         /* Version */
-        if (sqlite3_bind_text(self->search_product, 2, version, -1, SQLITE_STATIC) != SQLITE_OK) {
+        if (sqlite3_bind_text(self->search_product[idx], 2, version, -1, SQLITE_STATIC) != SQLITE_OK) {
                 fprintf(stderr, "cve_db_get_issues(): %s\n", sqlite3_errmsg(self->db));
                 goto bail;
         }
 
-        while ((rc = sqlite3_step(self->search_product) == SQLITE_ROW)) {
-                list = g_list_append(list, g_strdup((const gchar*)sqlite3_column_text(self->search_product, 0)));
+        /* Version */
+	if (idx)
+        	if (sqlite3_bind_text(self->search_product[idx], 3, vendor, -1, SQLITE_STATIC) != SQLITE_OK) {
+	                fprintf(stderr, "cve_db_get_issues(): %s\n", sqlite3_errmsg(self->db));
+                	goto bail;
+        	}
+
+        while ((rc = sqlite3_step(self->search_product[idx]) == SQLITE_ROW)) {
+                list = g_list_append(list, g_strdup((const gchar*)sqlite3_column_text(self->search_product[idx], 0)));
         }
         if (rc != SQLITE_OK) {
                 fprintf(stderr, "cve_db_get_issues(): %s\n", sqlite3_errmsg(self->db));
@@ -645,7 +664,22 @@ CveDB *cve_db_new(const char *path)
                 cve_db_free(ret);
                 return NULL;
         }
-        ret->search_product = stm;
+        ret->search_product[0] = stm;
+        stm = NULL;
+
+        /* Search product and vendor. */
+        if (use_frac_compare) {
+                q = "select ID, PRODUCT, VERSION from PRODUCTS where PRODUCT = ? and VENDOR = ?";
+        } else {
+                q = "SELECT ID FROM PRODUCTS WHERE PRODUCT = ? AND VERSION = ? COLLATE NOCASE and VENDOR = ?";
+        }
+        rc = sqlite3_prepare_v2(ret->db, q, -1, &stm, NULL);
+        if (rc != SQLITE_OK) {
+                fprintf(stderr, "cve_db_new(): %s\n", sqlite3_errmsg(ret->db));
+                cve_db_free(ret);
+                return NULL;
+        }
+        ret->search_product[1] = stm;
         stm = NULL;
 
         /* Get CVE. */
@@ -673,8 +707,11 @@ void cve_db_free(CveDB *self)
      if (self->insert_product) {
              sqlite3_finalize(self->insert_product);
      }
-     if (self->search_product) {
-             sqlite3_finalize(self->search_product);
+     if (self->search_product[0]) {
+             sqlite3_finalize(self->search_product[0]);
+     }
+     if (self->search_product[1]) {
+             sqlite3_finalize(self->search_product[1]);
      }
      if (self->get_cve) {
              sqlite3_finalize(self->get_cve);
diff --git a/src/core.h b/src/core.h
index 7a18b7d..4cdc785 100644
--- a/src/core.h
+++ b/src/core.h
@@ -84,8 +84,8 @@ struct cve_entry_t *cve_db_get_cve(CveDB *db, char *id);
  *
  * @return A newly allocated list of strings if found, otherwise NULL
  */
-GList *cve_db_get_issues(CveDB *db, char *product, char *version, GList *in);
-GList *cve_db_get_issues_frac_compare(CveDB *db, char *product, char *version,
+GList *cve_db_get_issues(CveDB *db, char *vendor, char *product, char *version, GList *in);
+GList *cve_db_get_issues_frac_compare(CveDB *db, char *vendor, char *product, char *version,
 				      GList *in);
 
 /**
diff --git a/src/main.c b/src/main.c
index 5ee6adb..26bfd1e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -114,16 +114,27 @@ static void cve_add_package_internal(struct source_package_t *pkg)
 
 	t = g_strsplit(q, " ", 10);
 	while (t[i]) {
+		gchar **p;
+		gchar *vendor, *product;
 		if (strlen(t[i]) == 0) {
 			i++;
 			continue;
 		}
+		p = g_strsplit(t[i], ":", 2);
+		if (p[1]) {
+			vendor = p[0];
+			product = p[1];
+		} else {
+			vendor = NULL;
+			product = p[0];
+		}
 		if (use_frac_compare)
 			issues = cve_db_get_issues_frac_compare(self->cve_db,
-					t[i], pkg->version, issues);
+					vendor, product, pkg->version, issues);
 		else
-			issues = cve_db_get_issues(self->cve_db, t[i],
-					pkg->version, issues);
+			issues = cve_db_get_issues(self->cve_db, vendor,
+					product, pkg->version, issues);
+		g_strfreev(p);
 		i++;
 	}
 	g_strfreev(t);
-- 
2.10.1