1<?php
2
3function split_into_words($sig) {
4    $words = array();
5    $u = 0;
6    do {
7	$words[$u] = substr($sig, $u, MAX_WORD_LENGTH);
8    } while (++$u < MAX_WORDS);
9
10    return $words;
11}
12
13function save_signature($url, $client_info, $md5, $cvec) {
14    $compressed_cvec = puzzle_compress_cvec($cvec);
15    $words = split_into_words($cvec);
16    $dbh = new PDO(DB_DSN);
17    $dbh->beginTransaction();
18    try {
19	$st = $dbh->prepare
20	  ('DELETE FROM sentpictures WHERE url = :url');
21	$st->execute(array(':url' => $url));
22	$st = $dbh->prepare
23	  ('SELECT id FROM pictures WHERE digest = :digest');
24	$st->execute(array(':digest' => $md5));
25	$picture_id = $st->fetchColumn();
26	$st->closeCursor();
27	$duplicate = TRUE;
28	if ($picture_id === FALSE) {
29	    $duplicate = FALSE;
30	    $st = $dbh->prepare
31	      ('INSERT INTO pictures (digest) VALUES (:digest)');
32	    $st->execute(array(':digest' => $md5));
33	    $picture_id = $dbh->lastInsertId('id');
34	}
35	$st = $dbh->prepare
36	  ('INSERT INTO sentpictures (url, sender, picture_id) ' .
37	   'VALUES (:url, :sender, :picture_id)');
38	$st->execute(array(':url' => $url, ':sender' => $client_info,
39			   ':picture_id' => $picture_id));
40	if ($duplicate === TRUE) {
41	    $dbh->commit();
42	    return TRUE;
43	}
44	$st = $dbh->prepare
45	  ('INSERT INTO signatures (compressed_signature, picture_id) ' .
46	   'VALUES(:compressed_signature, :picture_id)');
47	$st->execute(array(':compressed_signature' => $compressed_cvec,
48			   ':picture_id' => $picture_id));
49	$signature_id = $dbh->lastInsertId('id');
50	$st = $dbh->prepare
51	  ('INSERT INTO words (pos_and_word, signature_id) ' .
52	   'VALUES (:pos_and_word, :signature_id)');
53	foreach ($words as $u => $word) {
54	    $st->execute(array('pos_and_word'
55			       => chr($u) . puzzle_compress_cvec($word),
56			       'signature_id' => $signature_id));
57	}
58	$dbh->commit();
59    } catch (Exception $e) {
60	var_dump($e);
61	$dbh->rollback();
62    }
63    return TRUE;
64}
65
66function find_similar_pictures($md5, $cvec,
67			       $threshold = PUZZLE_CVEC_SIMILARITY_THRESHOLD) {
68    $compressed_cvec = puzzle_compress_cvec($cvec);
69    $words = split_into_words($cvec);
70    $dbh = new PDO(DB_DSN);
71    $dbh->beginTransaction();
72    $sql = 'SELECT DISTINCT(signature_id) AS signature_id FROM words ' .
73      'WHERE pos_and_word IN (';
74    $coma = FALSE;
75    foreach ($words as $u => $word) {
76	if ($coma === TRUE) {
77	    $sql .= ',';
78	}
79	$sql .= $dbh->quote(chr($u) . puzzle_compress_cvec($word));
80	$coma = TRUE;
81    }
82    $sql .= ')';
83    $res_words = $dbh->query($sql);
84    $scores = array();
85    $st = $dbh->prepare('SELECT compressed_signature, picture_id ' .
86			'FROM signatures WHERE id = :id');
87    while (($signature_id = $res_words->fetchColumn()) !== FALSE) {
88	$st->execute(array(':id' => $signature_id));
89	$row = $st->fetch();
90	$found_compressed_signature = $row['compressed_signature'];
91	$picture_id = $row['picture_id'];
92	$found_cvec = puzzle_uncompress_cvec($found_compressed_signature);
93	$distance = puzzle_vector_normalized_distance($cvec, $found_cvec);
94	if ($distance < $threshold && $distance > 0.0) {
95	    $scores[$picture_id] = $distance;
96	}
97    }
98    $sql = 'SELECT url FROM sentpictures WHERE picture_id IN (';
99    $coma = FALSE;
100    foreach ($scores as $picture_id => $score) {
101	if ($coma === TRUE) {
102	    $sql .= ',';
103	}
104	$sql .= $dbh->quote($picture_id);
105	$coma = TRUE;
106    }
107    $sql .= ')';
108    $urls = array();
109    if (!empty($scores)) {
110	$res_urls = $dbh->query($sql);
111	while (($url = $res_urls->fetchColumn()) !== FALSE) {
112	    array_push($urls, $url);
113	}
114    }
115    $dbh->commit();
116
117    return $urls;
118}
119
120?>
121