2017-09-09 21 views
1

WebExtensions에 Firefox 부가 기능 SDK 확장을 포팅합니다. 이전에 브라우저의 검색 엔진에 액세스 할 수 있었지만 지금은 할 수 없으므로 유용한 사용자가 모든 설치된 엔진이있는 search.json.mozlz4 파일을 읽으라고 제안했습니다. 그러나이 파일은 LZ4 압축을 사용하는 json이며 Mozilla의 own LZ4 format에 사용자 지정 마법 번호 인 'mozLz40 \ 0'이 있습니다.WebExtensions (JavaScript, Firefox)에서 LZ4 압축 텍스트 파일 (mozlz4) 읽기

하기 전에, 하나는 mozlz4 파일을 포함 LZ4 압축을 사용하여 텍스트 파일 읽기이를 사용할 수 있습니다

let bytes = OS.File.read(path, { compression: "lz4" }); 
let content = new TextDecoder().decode(bytes); 

(필자는 "압축"필드에 대한 문서를 찾을 수 있지만, 작동을) 파일을 읽는 것은

var reader = new FileReader(); 
reader.readAsText(file); 
reader.onload = function(ev) { 
    let content = ev.target.result; 
}; 

이 어떤 방식으로 압축을 처리하지 않습니다이다와

지금, WebExtensions를 사용하여, 최고의 내가 올 수 있습니다. This library은 LZ4 을 처리하지만 node.js 용이므로 사용할 수 없습니다. [편집 : 독립 실행 형].

import lz4 
file_obj = open("search.json.mozlz4", "rb") 
if file_obj.read(8) != b"mozLz40\0": 
    raise InvalidHeader("Invalid magic number") 
print(lz4.block.decompress(file_obj.read())) 

가 어떻게이 JS에서 할 수있는이 파이썬 코드, 비교, 예상대로 작동하는 동안 그러나, 나는 사용자 정의 매직 번호 처리를 제거하더라도 나는 그것이 파일을 압축을 얻을 수 없다?

+0

고맙게도, 나는 실수로 node-lz4가 실제로 독립 실행 형으로 작동하여 래퍼를 피하기 위해'require'를 구현했습니다. 그러나, 사용자 지정 lz4 매직 번호가있는 특정 mozlz4 형식을 처리하는 것처럼 보이지는 않습니다 (데이터와 해당 확인에서 매직 번호를 제거하더라도). 나는이 모든 질문을 업데이트했다. – CanisLupus

답변

2

많은 시행 착오 끝에 WebExtension에서 search.json.mozlz4 파일을 읽고 디코딩 할 수있었습니다.

// This method's code was taken from node-lz4 by Pierre Curto. MIT license. 
// CHANGES: Added ; to all lines. Reformated one-liners. Removed n = eIdx. Fixed eIdx skipping end bytes if sIdx != 0. 
function decodeLz4Block(input, output, sIdx, eIdx) 
{ 
    sIdx = sIdx || 0; 
    eIdx = eIdx || input.length; 

    // Process each sequence in the incoming data 
    for (var i = sIdx, j = 0; i < eIdx;) 
    { 
     var token = input[i++]; 

     // Literals 
     var literals_length = (token >> 4); 
     if (literals_length > 0) { 
      // length of literals 
      var l = literals_length + 240; 
      while (l === 255) { 
       l = input[i++]; 
       literals_length += l; 
      } 

      // Copy the literals 
      var end = i + literals_length; 
      while (i < end) { 
       output[j++] = input[i++]; 
      } 

      // End of buffer? 
      if (i === eIdx) { 
       return j; 
      } 
     } 

     // Match copy 
     // 2 bytes offset (little endian) 
     var offset = input[i++] | (input[i++] << 8); 

     // 0 is an invalid offset value 
     if (offset === 0 || offset > j) { 
      return -(i-2); 
     } 

     // length of match copy 
     var match_length = (token & 0xf); 
     var l = match_length + 240; 
     while (l === 255) { 
      l = input[i++]; 
      match_length += l; 
     } 

     // Copy the match 
     var pos = j - offset; // position of the match copy in the current output 
     var end = j + match_length + 4; // minmatch = 4 
     while (j < end) { 
      output[j++] = output[pos++]; 
     } 
    } 

    return j; 
} 

그런 다음이 함수를 선언 : - uncompress는 (외부 액세스에 대한 decodeBlock로 별칭) - 그래서 decodeLz4Block에 이름과 약간의 변화와 여기에 포함 당신이 하나 개의 기능을해야하지만 당신은 node-lz4 library 사용할 수 있습니다 사용자의 검색 및 선택 search.json.mozlz4을 할 수

function readMozlz4File(file, onRead, onError) 
{ 
    let reader = new FileReader(); 

    reader.onload = function() { 
     let input = new Uint8Array(reader.result); 
     let output; 
     let uncompressedSize = input.length*3; // size estimate for uncompressed data! 

     // Decode whole file. 
     do { 
      output = new Uint8Array(uncompressedSize); 
      uncompressedSize = decodeLz4Block(input, output, 8+4); // skip 8 byte magic number + 4 byte data size field 
      // if there's more data than our output estimate, create a bigger output array and retry (at most one retry) 
     } while (uncompressedSize > output.length); 

     output = output.slice(0, uncompressedSize); // remove excess bytes 

     let decodedText = new TextDecoder().decode(output); 
     onRead(decodedText); 
    }; 

    if (onError) { 
     reader.onerror = onError; 
    } 

    reader.readAsArrayBuffer(file); // read as bytes 
}; 

그런 다음 당신은 당신의 설정을 추가 페이지에 HTML 버튼을 추가 할 수 있습니다 그 파일 객체 (안 경로) 성공/오류 콜백을 수신 (WebExtensions에서는 사용자의 개입없이 파일 시스템의 어떤 파일도 열 수 없습니다) :

<input name="selectMozlz4FileButton" type="file" accept=".json.mozlz4"> 

우리가 이전에 선언 된 메소드를 호출하는 사용하여 파일을 선택하여 사용자에게이 같은 응답합니다 (I 오류 콜백을 사용하지 않는 여기를,하지만 당신은 할 수 있습니다) :

let button = document.getElementsByName("selectMozlz4FileButton")[0]; 
button.onchange = function onButtonPress(ev) { 
    let file = ev.target.files[0]; 
    readMozlz4File(file, function(text){ 
     console.log(text); 
    }); 
}; 

도움이되기를 바랍니다. 나는이 간단한 일을하는 데 많은 시간을 할애했다. :)