Generating URL-friendly unique string with embedded datetime
I'm personally tired of reimplementing "a ticket" mechanism for my web projects for some one-time operations like account activation or password reset. I know it's simple but it requires me to keep (and persist!) two pieces of data: a ticket itself and an expiration date.
So I have this idea, to generate a unique string with e开发者_StackOverflow社区mbedded datetime (expiration date) in it, which we can check upon receiving as a part of url-request.
I've started with this:
var clearTicket = Convert.ToInt64(expiration.ToString("yyyyMMddhhmm")).ToString("x12") + key.ToString("N");
But I want it to be more compact. Something BaseXX-ish I suppose. Any ideas how to implement this encoding/decoding efficiently (considering url-safe charset)?
It took me some time, so I hope it helps:
First of all, you should substract 200000000000 from "yyyyMMddhhmm", because you actually don't need the first two digits for the next 88 years.
Here is the implementation for encoding and decoding Base64, using only URL-safe characters.
If you have any questions, feel free to ask.
public string Base64Encode (Int64 Number)
{
string HelpString = "";
if (Number >= 64)
{
HelpString = Base64Encode(Number / 64);
}
return (HelpString += Base64EncodeHelper(Number % 64));
}
public string Base64EncodeHelper(Int64 Number)
{
string HelpString = "";
Number += 65;
if ((Number >= 65 && Number <= 90) || (Number >= 97 && Number <= 122)) // 0 - 25 and 32 - 57
{
HelpString = Convert.ToString((char)Number);
}
else if (Number >= 91 && Number <= 96) // 26 - 31
{
HelpString = Convert.ToString((char)(Number - 43));
}
else if (Number >= 123 && Number <= 126) // 58 - 61
{
HelpString = Convert.ToString((char)(Number - 69));
}
else if (Number == 127) // 62
{
HelpString = "-";
}
else // 63
{
HelpString = "_";
}
return (HelpString);
}
public Int64 Base64Decode(string Encoded)
{
Int64 Result = 0, HelpInt = 0;
int i = Encoded.Length - 1;
foreach (char Character in Encoded)
{
int CharInInt = (int)Character;
if (Character == '_')
{
HelpInt = 63;
}
else if (Character == '-')
{
HelpInt = 62;
}
else if (((CharInInt + 69) >= 123) && ((CharInInt + 69) <= 126))
{
HelpInt = CharInInt + 4;
}
else if (((CharInInt + 43) >= 91) && ((CharInInt + 43) <= 96))
{
HelpInt = CharInInt - 22;
}
else
{
HelpInt = CharInInt - 65;
}
Result += Convert.ToInt64((Math.Pow(64, Convert.ToDouble(i))) * HelpInt);
i--;
}
return Result;
}
You can extend string like this:
public static string ToURLParameter(this string text)
{
if (String.IsNullOrEmpty(text)) return "";
// to lowercase, trim extra spaces
text = text.Trim();
var len = text.Length;
var sb = new StringBuilder(len);
bool prevdash = false;
char c;
//
text = text.Replace('Å', 'A');
text = text.Replace('å', 'a');
text = text.Replace('Ä', 'A');
text = text.Replace('ä', 'a');
text = text.Replace('Ö', 'O');
text = text.Replace('ö', 'o');
for (int i = 0; i < text.Length; i++)
{
c = text[i];
if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-')
{
if (!prevdash)
{
sb.Append('-');
prevdash = true;
}
}
else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z'))
{
sb.Append(c);
prevdash = false;
}
if (i == 80) break;
}
text = sb.ToString();
// remove trailing dash, if there is one
if (text.EndsWith("-"))
text = text.Substring(0, text.Length - 1);
return text;
}
and then you can use it on any variable that is string like:
string something = "asdfljasdklf";
<%= something.ToUrlParameter() %>
I've finally created a solution using techniques described in these answers:
Compressing big number (or string) to small value
How do you convert Byte Array to Hexadecimal String, and vice versa?
Works great!
Thanks you all for your help!
精彩评论