Page MenuHomeSoftware Heritage

search.js
No OneTemporary

search.js

/**
* Search page management
* Args:
* textForm: the form containing the text input, if any
* fileForm: the form containing the file input, if any
* messageElem: the element that should display search messages
*/
var SearchFormController = function(textForm, fileForm, messageElem)
{
this.textForm = textForm;
this.fileForm = fileForm;
this.messageElem = messageElem;
// List of hashes to check against files being processed
this.hashed_already = {
'sha1': {},
'sha256': {},
'sha1_git': {}
};
this.algos = ['sha1', 'sha256', 'sha1_git'];
this.CHECKSUM_RE = /^([0-9a-f]{40}|[0-9a-f]{64})$/i;
var self = this;
/**
* Show search messages on the page
* Args:
* msg: the message to show
*/
this.searchMessage = function(msg) {
self.messageElem.empty();
self.messageElem.text(msg);
};
/**
* Setup the text field
* Args:
* textFormInput: the text form's input
*/
this.setupTextForm = function(textFormInput) {
self.textForm.submit(function(event) {
var q = textFormInput.val();
if (!q) {
event.preventDefault();
self.searchMessage("Please enter a SHA-1 or SHA-256 checksum.");
}
else if (q && !q.match(self.CHECKSUM_RE)) {
event.preventDefault();
self.searchMessage("Invalid SHA-1 or SHA-256 checksum");
}
});
};
/**
* Setup the file drag&drop UI and hashing support.
* Args:
* fileDropElem: the element receptive to drag & drop
* hashedListerElem: the element that receives the hased file descriptions
* fileFormInput: the input that actually receives files
* clearButton: the button used to clear currently hashed files
*/
this.setupFileForm = function(fileDropElem, hashedListerElem, fileFormInput, clearButton) {
if (!FileReader || !CryptoJS) {
self.searchMessage("Client-side file hashing is not available for your browser.");
return;
}
// Enable clicking on the text element for file picker
fileDropElem.click(function(event) {
event.preventDefault();
fileFormInput.click();
});
// Enable drag&drop
var makeDroppable = function(fileReceptionElt) {
var fileshovering = false;
fileReceptionElt.on('dragover', function(event) {
event.stopPropagation();
event.preventDefault();
});
fileReceptionElt.on('dragenter', function(event) {
event.stopPropagation();
event.preventDefault();
if (!fileshovering) {
fileReceptionElt.css("border-style", "solid");
fileReceptionElt.css("box-shadow", "inset 0 3px 4px");
fileshovering = true;
}
});
fileReceptionElt.on('dragover', function(event) {
event.stopPropagation();
event.preventDefault();
if (!fileshovering) {
fileReceptionElt.css("border-style", "solid");
fileReceptionElt.css("box-shadow", "inset 0 3px 4px");
fileshovering = true;
}
});
fileReceptionElt.on('dragleave', function(event) {
event.stopPropagation();
event.preventDefault();
if (fileshovering) {
fileReceptionElt.css("border-style", "dashed");
fileReceptionElt.css("box-shadow", "none");
fileshovering = false;
}
});
fileReceptionElt.on('drop', function(event) {
event.stopPropagation();
event.preventDefault();
if (fileshovering) {
fileReceptionElt.css("border-style", "dashed");
fileReceptionElt.css("box-shadow", "none");
fileshovering = false;
}
var myfiles = event.originalEvent.dataTransfer.files;
readAndHash(myfiles);
});
};
makeDroppable(fileDropElem);
// Connect input change and rehash
var makeInputChange = function(fileInput) {
return fileInput.each(function() {
$(this).on('change', function(){
readAndHash(this.files);
});
});
};
makeInputChange(fileFormInput);
// Connect clear button
var makeClearButton = function(button) {
return button.each(function() {
$(this).click(function(event) {
event.preventDefault();
hashedListerElem.empty();
self.fileForm.children('.search-hidden').remove();
self.hashed_already = {
'sha1': {},
'sha256': {},
'sha1_git': {}
};
});
});
};
makeClearButton(clearButton);
var readAndHash = function(filelist) {
for (var file_idx = 0; file_idx < filelist.length; file_idx++) {
var file = filelist.item(file_idx);
var fr = new FileReader();
bindReader(fr, file.name);
fr.readAsArrayBuffer(file);
}
};
var bindReader = function(freader, fname) {
freader.onloadend = function(event) {
if (event.target.readyState == FileReader.DONE)
return dedupAndAdd(event.target.result, fname);
else
return null;
};
};
/**
* Hash the buffer with SHA-1, SHA-1_GIT, SHA-256
* Args:
* buffer: the buffer to hash
* fname: the file name corresponding to the buffer
* Returns:
* a dict of algo_hash: hash
*/
var hashBuffer = function (buffer, fname) {
function str2ab(header) {
var buf = new ArrayBuffer(header.length);
var view = new Uint8Array(buf); // byte view, all we need is ASCII
for (var idx = 0, len=header.length; idx < len; idx++)
view[idx] = header.charCodeAt(idx);
return buf;
}
var content_array = CryptoJS.lib.WordArray.create(buffer);
var git_hd_str = 'blob ' + buffer.byteLength + '\0';
var git_hd_buffer = str2ab(git_hd_str);
var git_hd_array = CryptoJS.lib.WordArray.create(git_hd_buffer);
var sha1 = CryptoJS.SHA1(content_array);
var sha256 = CryptoJS.SHA256(content_array);
var sha1_git = CryptoJS.SHA1(git_hd_array.concat(content_array));
return {
'sha1': sha1 + '',
'sha256': sha256 + '',
'sha1_git': sha1_git + ''
};
};
/**
* Hash the buffer and add it to the form if it is unique
* If not, display which file has the same content
* Args:
* buffer: the buffer to hash
* fname: the file name corresponding to the buffer
*/
var dedupAndAdd = function(buffer, fname) {
var hashes = hashBuffer(buffer);
var has_duplicate = false;
for (var algo_s in hashes) {
if (self.hashed_already[algo_s][hashes[algo_s]] != undefined) {
// Duplicate content -- fileLister addition only, as duplicate
hashedListerElem.append($('<div>')
.addClass('span3')
.text(fname + ': duplicate of ' + self.hashed_already[algo_s][hashes[algo_s]]));
has_duplicate = true;
break;
}
}
// First file read with this content -- fileLister and form addition
if (!has_duplicate) {
// Add to hashed list
for (var algo_c in self.hashed_already)
self.hashed_already[algo_c][hashes[algo_c]] = fname;
hashedListerElem.append($('<div>')
.addClass('span3')
.text(fname));
var hashstring = JSON.stringify(hashes).replace('\"', '\'');
self.fileForm.append($("<input>", {type: 'hidden',
class: 'search-hidden',
name: fname,
value: hashes['sha1']}// hashstring}
));
}
};
};
};

File Metadata

Mime Type
text/x-asm
Expires
Sat, Jun 21, 6:52 PM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3353175

Event Timeline