Created
May 3, 2018 16:22
-
-
Save danrouse/52212f0de2fbfe33cfc56583f20ccb74 to your computer and use it in GitHub Desktop.
gmail `compose` query parameter encoder/decoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fullAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | |
const restrictedAlphabet = 'BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz'; | |
const threadPrefix = 'thread-'; | |
const messagePrefix = 'msg-'; | |
const isWhitespace = str => /^[\s\xa0]*$/.test(str); | |
const isInvalidString = str => str ? (str.indexOf(threadPrefix) !== -1 || str.indexOf(messagePrefix) !== -1) : false; | |
const encode = function(str) { | |
if (isWhitespace(str)) return str; | |
str = str.replace(threadPrefix, ''); | |
return transliterate(btoa(str).replace(/=/g, ''), fullAlphabet, restrictedAlphabet); | |
}; | |
const decode = function(str) { | |
if (isInvalidString(str) || !/^[BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz]*$/.test(str)) return str; | |
try { | |
const transliterated = atob(transliterate(str, restrictedAlphabet, fullAlphabet)) | |
return transliterated.indexOf(threadPrefix) === -1 ? threadPrefix + transliterated : transliterated; | |
} catch (err) { | |
return str; | |
} | |
}; | |
const transliterate = function(subject, inputAlphabet, outputAlphabet) { | |
if (!outputAlphabet) throw Error('rd'); | |
let i, j; | |
const inputAlphabetSize = inputAlphabet.length; | |
const outputAlphabetSize = outputAlphabet.length; | |
let isEqual = true; | |
for (i = 0; i < subject.length; i++) | |
if (subject.charAt(i) != inputAlphabet.charAt(0)) { | |
isEqual = false; | |
break; | |
} | |
if (isEqual) return outputAlphabet.charAt(0); | |
const inputAlphabetMap = {}; | |
for (i = 0; i < inputAlphabetSize; i++) inputAlphabetMap[inputAlphabet.charAt(i)] = i; | |
const inputIndices = []; | |
for (i = subject.length - 1; i >= 0; i--) { | |
const char = subject.charAt(i); | |
if (typeof inputAlphabetMap[char] === 'undefined') throw Error("sd`" + subject + "`" + inputAlphabet + "`" + char); | |
inputIndices.push(inputAlphabetMap[char]); | |
} | |
const outputIndices = []; | |
for (i = inputIndices.length - 1; i >= 0; i--) { | |
let offset = 0; | |
for (j = 0; j < outputIndices.length; j++) { | |
let index = outputIndices[j] * inputAlphabetSize + offset; | |
if (index >= outputAlphabetSize) { | |
const remainder = index % outputAlphabetSize; | |
offset = (index - remainder) / outputAlphabetSize; | |
index = remainder; | |
} else { | |
offset = 0; | |
} | |
outputIndices[j] = index; | |
} | |
while (offset) { | |
const remainder = offset % outputAlphabetSize; | |
outputIndices.push(remainder); | |
offset = (offset - remainder) / outputAlphabetSize; | |
} | |
offset = inputIndices[i]; | |
for (j = 0; offset; j++) { | |
if (j >= outputIndices.length) outputIndices.push(0); | |
let index = outputIndices[j] + offset; | |
if (index >= outputAlphabetSize) { | |
const remainder = index % outputAlphabetSize; | |
offset = (index - remainder) / outputAlphabetSize; | |
index = remainder; | |
} else { | |
offset = 0; | |
} | |
outputIndices[j] = index; | |
} | |
} | |
const outputBuffer = []; | |
for (i = outputIndices.length - 1; i >= 0; i--) { | |
const index = outputIndices[i]; | |
if (index >= outputAlphabet.length || index < 0) throw Error("td`" + outputIndices + "`" + index); | |
outputBuffer.push(outputAlphabet.charAt(index)); | |
} | |
return outputBuffer.join(''); | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Related - https://stackoverflow.com/questions/50800330/gmail-api-does-not-support-new-thread-ids