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