Browse Source

Merge pull request #11 from shadowsocks/master

Merge with upstream
pull/146/head
Sharuru 10 years ago
parent
commit
a137041461
42 changed files with 3117 additions and 1576 deletions
  1. +8
    -0
      CHANGES
  2. +26
    -0
      CONTRIBUTING.md
  3. +30
    -12
      LICENSE.txt
  4. +6
    -0
      packaging/upload.sh
  5. +0
    -1209
      shadowsocks-csharp/3rd/QRCodeCS.cs
  6. +0
    -61
      shadowsocks-csharp/3rd/SimpleJson.cs
  7. +160
    -0
      shadowsocks-csharp/3rd/zxing/BitArray.cs
  8. +40
    -0
      shadowsocks-csharp/3rd/zxing/BlockPair.cs
  9. +148
    -0
      shadowsocks-csharp/3rd/zxing/ByteMatrix.cs
  10. +526
    -0
      shadowsocks-csharp/3rd/zxing/Encoder.cs
  11. +109
    -0
      shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs
  12. +163
    -0
      shadowsocks-csharp/3rd/zxing/GenericGF.cs
  13. +230
    -0
      shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs
  14. +271
    -0
      shadowsocks-csharp/3rd/zxing/MaskUtil.cs
  15. +604
    -0
      shadowsocks-csharp/3rd/zxing/MatrixUtil.cs
  16. +115
    -0
      shadowsocks-csharp/3rd/zxing/Mode.cs
  17. +91
    -0
      shadowsocks-csharp/3rd/zxing/QRCode.cs
  18. +84
    -0
      shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs
  19. +342
    -0
      shadowsocks-csharp/3rd/zxing/Version.cs
  20. +52
    -36
      shadowsocks-csharp/Controller/AutoStartup.cs
  21. +1
    -1
      shadowsocks-csharp/Controller/Local.cs
  22. +26
    -2
      shadowsocks-csharp/Controller/Logging.cs
  23. +2
    -2
      shadowsocks-csharp/Controller/UpdateChecker.cs
  24. +1
    -1
      shadowsocks-csharp/Data/cn.txt
  25. BIN
      shadowsocks-csharp/Data/polipo.exe.gz
  26. +1
    -1
      shadowsocks-csharp/Encryption/EncryptorBase.cs
  27. +1
    -1
      shadowsocks-csharp/Encryption/EncryptorFactory.cs
  28. +1
    -1
      shadowsocks-csharp/Encryption/IEncryptor.cs
  29. +1
    -1
      shadowsocks-csharp/Encryption/IVEncryptor.cs
  30. +1
    -1
      shadowsocks-csharp/Encryption/PolarSSL.cs
  31. +1
    -1
      shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs
  32. +1
    -1
      shadowsocks-csharp/Encryption/Sodium.cs
  33. +1
    -1
      shadowsocks-csharp/Encryption/SodiumEncryptor.cs
  34. +1
    -1
      shadowsocks-csharp/Encryption/TableEncryptor.cs
  35. +1
    -1
      shadowsocks-csharp/Properties/AssemblyInfo.cs
  36. +0
    -26
      shadowsocks-csharp/Properties/Settings.Designer.cs
  37. +0
    -7
      shadowsocks-csharp/Properties/Settings.settings
  38. +39
    -152
      shadowsocks-csharp/View/MenuViewController.cs
  39. +8
    -36
      shadowsocks-csharp/View/QRCodeForm.cs
  40. +23
    -19
      shadowsocks-csharp/shadowsocks-csharp.csproj
  41. +1
    -1
      test/Properties/AssemblyInfo.cs
  42. +1
    -1
      test/UnitTest.cs

+ 8
- 0
CHANGES View File

@@ -1,3 +1,11 @@
2.1.6 2015-01-02
- Fix OPTIONS requests
- Improve logs

2.1.5 2014-12-25
- Fix QR Code compatibility with iOS
- Only left button will trigger double click on tray icon

2.1.4 2014-12-20
- Fix crash when remarks are too long



+ 26
- 0
CONTRIBUTING.md View File

@@ -0,0 +1,26 @@
How to Contribute
=================

Pull Requests
-------------

1. Pull requests are welcome. If you would like to add a large feature
or make a significant change, make sure to open an issue to discuss with
people first.
2. Make sure to pass the unit tests. Write unit tests for new modules if
needed.

Issues
------

1. Only bugs and feature requests are accepted here.
2. We'll only work on important features. If the feature you're asking only
benefits a few people, you'd better implement the feature yourself and send us
a pull request, or ask some of your friends to do so.
3. We don't answer questions of any other types here. Since very few people
are watching the issue tracker here, you'll probably get no help from here.
Read [Troubleshooting] and get help from forums or [mailing lists].


[Troubleshooting]: https://github.com/clowwindy/shadowsocks/wiki/Troubleshooting
[mailing lists]: https://groups.google.com/forum/#!forum/shadowsocks

+ 30
- 12
LICENSE.txt View File

@@ -1,7 +1,7 @@
shadowsocks-csharp
==================
Copyright (C) 2014 clowwindy <clowwindy42@gmail.com>
Copyright (C) 2015 clowwindy <clowwindy42@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -81,20 +81,38 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
qrcodejs
--------
ZXing
-----
Copyright 2007 ZXing authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
QRCode for C#4.0 Silverlight is translation of QRCode for JavaScript
https://github.com/jeromeetienne/jquery-qrcode/
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2009 Kazuhiko Arase
URL: http://www.d-project.com/
libsodium
---------
Licensed under the MIT license:
http://www.opensource.org/licenses/mit-license.php
Copyright (c) 2013-2015
Frank Denis <j at pureftpd dot org>
The word "QR Code" is registered trademark of
DENSO WAVE INCORPORATED
http://www.denso-wave.com/qrcode/faqpatent-e.html
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 6
- 0
packaging/upload.sh View File

@@ -0,0 +1,6 @@
#!/bin/bash

version=$1

rsync --progress -e ssh shadowsocks-csharp/bin/x86/Release/Shadowsocks-win-dotnet4.0-$1.zip frs.sourceforge.net:/home/frs/project/shadowsocksgui/dist/
rsync --progress -e ssh shadowsocks-csharp/bin/x86/Release/Shadowsocks-win-$1.zip frs.sourceforge.net:/home/frs/project/shadowsocksgui/dist/

+ 0
- 1209
shadowsocks-csharp/3rd/QRCodeCS.cs
File diff suppressed because it is too large
View File


+ 0
- 61
shadowsocks-csharp/3rd/SimpleJson.cs View File

@@ -589,67 +589,6 @@ namespace SimpleJson
return SerializeObject(json, CurrentJsonSerializerStrategy);
}
public static string EscapeToJavascriptString(string jsonString)
{
if (string.IsNullOrEmpty(jsonString))
{
return jsonString;
}
StringBuilder sb = new StringBuilder();
char c;
for (int i = 0; i < jsonString.Length; )
{
c = jsonString[i++];
if (c == '\\')
{
int remainingLength = jsonString.Length - i;
if (remainingLength >= 2)
{
char lookahead = jsonString[i];
if (lookahead == '\\')
{
sb.Append('\\');
++i;
}
else if (lookahead == '"')
{
sb.Append("\"");
++i;
}
else if (lookahead == 't')
{
sb.Append('\t');
++i;
}
else if (lookahead == 'b')
{
sb.Append('\b');
++i;
}
else if (lookahead == 'n')
{
sb.Append('\n');
++i;
}
else if (lookahead == 'r')
{
sb.Append('\r');
++i;
}
}
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
protected static IDictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
{
IDictionary<string, object> table = new JsonObject();


+ 160
- 0
shadowsocks-csharp/3rd/zxing/BitArray.cs View File

@@ -0,0 +1,160 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.Common
{
/// <summary>
/// A simple, fast array of bits, represented compactly by an array of ints internally.
/// </summary>
/// <author>Sean Owen</author>
public sealed class BitArray
{
private int[] bits;
private int size;
public int Size
{
get
{
return size;
}
}
public int SizeInBytes
{
get
{
return (size + 7) >> 3;
}
}
public bool this[int i]
{
get
{
return (bits[i >> 5] & (1 << (i & 0x1F))) != 0;
}
}
public BitArray()
{
this.size = 0;
this.bits = new int[1];
}
private void ensureCapacity(int size)
{
if (size > bits.Length << 5)
{
int[] newBits = makeArray(size);
System.Array.Copy(bits, 0, newBits, 0, bits.Length);
bits = newBits;
}
}
/// <summary>
/// Appends the bit.
/// </summary>
/// <param name="bit">The bit.</param>
public void appendBit(bool bit)
{
ensureCapacity(size + 1);
if (bit)
{
bits[size >> 5] |= 1 << (size & 0x1F);
}
size++;
}
/// <summary>
/// Appends the least-significant bits, from value, in order from most-significant to
/// least-significant. For example, appending 6 bits from 0x000001E will append the bits
/// 0, 1, 1, 1, 1, 0 in that order.
/// </summary>
/// <param name="value"><see cref="int"/> containing bits to append</param>
/// <param name="numBits">bits from value to append</param>
public void appendBits(int value, int numBits)
{
if (numBits < 0 || numBits > 32)
{
throw new ArgumentException("Num bits must be between 0 and 32");
}
ensureCapacity(size + numBits);
for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--)
{
appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1);
}
}
public void appendBitArray(BitArray other)
{
int otherSize = other.size;
ensureCapacity(size + otherSize);
for (int i = 0; i < otherSize; i++)
{
appendBit(other[i]);
}
}
public void xor(BitArray other)
{
if (bits.Length != other.bits.Length)
{
throw new ArgumentException("Sizes don't match");
}
for (int i = 0; i < bits.Length; i++)
{
// The last byte could be incomplete (i.e. not have 8 bits in
// it) but there is no problem since 0 XOR 0 == 0.
bits[i] ^= other.bits[i];
}
}
/// <summary>
/// Toes the bytes.
/// </summary>
/// <param name="bitOffset">first bit to start writing</param>
/// <param name="array">array to write into. Bytes are written most-significant byte first. This is the opposite
/// of the internal representation, which is exposed by BitArray</param>
/// <param name="offset">position in array to start writing</param>
/// <param name="numBytes">how many bytes to write</param>
public void toBytes(int bitOffset, byte[] array, int offset, int numBytes)
{
for (int i = 0; i < numBytes; i++)
{
int theByte = 0;
for (int j = 0; j < 8; j++)
{
if (this[bitOffset])
{
theByte |= 1 << (7 - j);
}
bitOffset++;
}
array[offset + i] = (byte)theByte;
}
}
private static int[] makeArray(int size)
{
return new int[(size + 31) >> 5];
}
}
}

+ 40
- 0
shadowsocks-csharp/3rd/zxing/BlockPair.cs View File

@@ -0,0 +1,40 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace ZXing.QrCode.Internal
{
internal sealed class BlockPair
{
private readonly byte[] dataBytes;
private readonly byte[] errorCorrectionBytes;
public BlockPair(byte[] data, byte[] errorCorrection)
{
dataBytes = data;
errorCorrectionBytes = errorCorrection;
}
public byte[] DataBytes
{
get { return dataBytes; }
}
public byte[] ErrorCorrectionBytes
{
get { return errorCorrectionBytes; }
}
}
}

+ 148
- 0
shadowsocks-csharp/3rd/zxing/ByteMatrix.cs View File

@@ -0,0 +1,148 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.QrCode.Internal
{
/// <summary>
/// JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned
/// 0, 1 and 2 I'm going to use less memory and go with bytes.
/// </summary>
/// <author>dswitkin@google.com (Daniel Switkin)</author>
public sealed class ByteMatrix
{
private readonly byte[][] bytes;
private readonly int width;
private readonly int height;
/// <summary>
/// Initializes a new instance of the <see cref="ByteMatrix"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public ByteMatrix(int width, int height)
{
bytes = new byte[height][];
for (var i = 0; i < height; i++)
bytes[i] = new byte[width];
this.width = width;
this.height = height;
}
/// <summary>
/// Gets the height.
/// </summary>
public int Height
{
get { return height; }
}
/// <summary>
/// Gets the width.
/// </summary>
public int Width
{
get { return width; }
}
/// <summary>
/// Gets or sets the <see cref="System.Int32"/> with the specified x.
/// </summary>
public int this[int x, int y]
{
get { return bytes[y][x]; }
set { bytes[y][x] = (byte)value; }
}
/// <summary>
/// an internal representation as bytes, in row-major order. array[y][x] represents point (x,y)
/// </summary>
public byte[][] Array
{
get { return bytes; }
}
/// <summary>
/// Sets the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="value">The value.</param>
public void set(int x, int y, byte value)
{
bytes[y][x] = value;
}
/// <summary>
/// Sets the specified x.
/// </summary>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <param name="value">if set to <c>true</c> [value].</param>
public void set(int x, int y, bool value)
{
bytes[y][x] = (byte)(value ? 1 : 0);
}
/// <summary>
/// Clears the specified value.
/// </summary>
/// <param name="value">The value.</param>
public void clear(byte value)
{
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
bytes[y][x] = value;
}
}
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
override public String ToString()
{
var result = new StringBuilder(2 * width * height + 2);
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
switch (bytes[y][x])
{
case 0:
result.Append(" 0");
break;
case 1:
result.Append(" 1");
break;
default:
result.Append(" ");
break;
}
}
result.Append('\n');
}
return result.ToString();
}
}
}

+ 526
- 0
shadowsocks-csharp/3rd/zxing/Encoder.cs View File

@@ -0,0 +1,526 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Text;
using ZXing.Common;
using ZXing.Common.ReedSolomon;
namespace ZXing.QrCode.Internal
{
/// <summary>
/// </summary>
/// <author>satorux@google.com (Satoru Takabayashi) - creator</author>
/// <author>dswitkin@google.com (Daniel Switkin) - ported from C++</author>
public static class Encoder
{
internal static String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1";
// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
// Basically it applies four rules and summate all penalties.
private static int calculateMaskPenalty(ByteMatrix matrix)
{
return MaskUtil.applyMaskPenaltyRule1(matrix)
+ MaskUtil.applyMaskPenaltyRule2(matrix)
+ MaskUtil.applyMaskPenaltyRule3(matrix)
+ MaskUtil.applyMaskPenaltyRule4(matrix);
}
/// <summary>
/// Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen
/// internally by chooseMode(). On success, store the result in "qrCode".
/// We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
/// "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
/// strong error correction for this purpose.
/// Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
/// with which clients can specify the encoding mode. For now, we don't need the functionality.
/// </summary>
/// <param name="content">text to encode</param>
/// <param name="ecLevel">error correction level to use</param>
/// <returns><see cref="QRCode"/> representing the encoded QR code</returns>
public static QRCode encode(String content, ErrorCorrectionLevel ecLevel)
{
// Determine what character encoding has been specified by the caller, if any
#if !SILVERLIGHT || WINDOWS_PHONE
String encoding = DEFAULT_BYTE_MODE_ENCODING;
//bool generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding);
#else
// Silverlight supports only UTF-8 and UTF-16 out-of-the-box
const string encoding = "UTF-8";
// caller of the method can only control if the ECI segment should be written
// character set is fixed to UTF-8; but some scanners doesn't like the ECI segment
bool generateECI = (hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET));
#endif
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use
// multiple modes / segments even if that were more efficient. Twould be nice.
Mode mode = Mode.BYTE;
// This will store the header information, like mode and
// length, as well as "header" segments like an ECI segment.
BitArray headerBits = new BitArray();
/*
// Append ECI segment if applicable
if (mode == Mode.BYTE && generateECI)
{
CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding);
if (eci != null)
{
var eciIsExplicitDisabled = (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) ? (bool)hints[EncodeHintType.DISABLE_ECI] : false);
if (!eciIsExplicitDisabled)
{
appendECI(eci, headerBits);
}
}
}
* */
// (With ECI in place,) Write the mode marker
appendModeInfo(mode, headerBits);
// Collect data within the main segment, separately, to count its size if needed. Don't add it to
// main payload yet.
BitArray dataBits = new BitArray();
appendBytes(content, mode, dataBits, encoding);
// Hard part: need to know version to know how many bits length takes. But need to know how many
// bits it takes to know version. First we take a guess at version by assuming version will be
// the minimum, 1:
int provisionalBitsNeeded = headerBits.Size
+ mode.getCharacterCountBits(Version.getVersionForNumber(1))
+ dataBits.Size;
Version provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel);
// Use that guess to calculate the right version. I am still not sure this works in 100% of cases.
int bitsNeeded = headerBits.Size
+ mode.getCharacterCountBits(provisionalVersion)
+ dataBits.Size;
Version version = chooseVersion(bitsNeeded, ecLevel);
BitArray headerAndDataBits = new BitArray();
headerAndDataBits.appendBitArray(headerBits);
// Find "length" of main segment and write it
int numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length;
appendLengthInfo(numLetters, version, mode, headerAndDataBits);
// Put data together into the overall payload
headerAndDataBits.appendBitArray(dataBits);
Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
int numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords;
// Terminate the bits properly.
terminateBits(numDataBytes, headerAndDataBits);
// Interleave data bits with error correction code.
BitArray finalBits = interleaveWithECBytes(headerAndDataBits,
version.TotalCodewords,
numDataBytes,
ecBlocks.NumBlocks);
QRCode qrCode = new QRCode
{
ECLevel = ecLevel,
Mode = mode,
Version = version
};
// Choose the mask pattern and set to "qrCode".
int dimension = version.DimensionForVersion;
ByteMatrix matrix = new ByteMatrix(dimension, dimension);
int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix);
qrCode.MaskPattern = maskPattern;
// Build the matrix and set it to "qrCode".
MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
qrCode.Matrix = matrix;
return qrCode;
}
private static int chooseMaskPattern(BitArray bits,
ErrorCorrectionLevel ecLevel,
Version version,
ByteMatrix matrix)
{
int minPenalty = Int32.MaxValue; // Lower penalty is better.
int bestMaskPattern = -1;
// We try all mask patterns to choose the best one.
for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++)
{
MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);
int penalty = calculateMaskPenalty(matrix);
if (penalty < minPenalty)
{
minPenalty = penalty;
bestMaskPattern = maskPattern;
}
}
return bestMaskPattern;
}
private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel)
{
// In the following comments, we use numbers of Version 7-H.
for (int versionNum = 1; versionNum <= 40; versionNum++)
{
Version version = Version.getVersionForNumber(versionNum);
// numBytes = 196
int numBytes = version.TotalCodewords;
// getNumECBytes = 130
Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
int numEcBytes = ecBlocks.TotalECCodewords;
// getNumDataBytes = 196 - 130 = 66
int numDataBytes = numBytes - numEcBytes;
int totalInputBytes = (numInputBits + 7) / 8;
if (numDataBytes >= totalInputBytes)
{
return version;
}
}
throw new Exception("Data too big");
}
/// <summary>
/// Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
/// </summary>
/// <param name="numDataBytes">The num data bytes.</param>
/// <param name="bits">The bits.</param>
internal static void terminateBits(int numDataBytes, BitArray bits)
{
int capacity = numDataBytes << 3;
if (bits.Size > capacity)
{
throw new Exception("data bits cannot fit in the QR Code" + bits.Size + " > " +
capacity);
}
for (int i = 0; i < 4 && bits.Size < capacity; ++i)
{
bits.appendBit(false);
}
// Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
// If the last byte isn't 8-bit aligned, we'll add padding bits.
int numBitsInLastByte = bits.Size & 0x07;
if (numBitsInLastByte > 0)
{
for (int i = numBitsInLastByte; i < 8; i++)
{
bits.appendBit(false);
}
}
// If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
int numPaddingBytes = numDataBytes - bits.SizeInBytes;
for (int i = 0; i < numPaddingBytes; ++i)
{
bits.appendBits((i & 0x01) == 0 ? 0xEC : 0x11, 8);
}
if (bits.Size != capacity)
{
throw new Exception("Bits size does not equal capacity");
}
}
/// <summary>
/// Get number of data bytes and number of error correction bytes for block id "blockID". Store
/// the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
/// JISX0510:2004 (p.30)
/// </summary>
/// <param name="numTotalBytes">The num total bytes.</param>
/// <param name="numDataBytes">The num data bytes.</param>
/// <param name="numRSBlocks">The num RS blocks.</param>
/// <param name="blockID">The block ID.</param>
/// <param name="numDataBytesInBlock">The num data bytes in block.</param>
/// <param name="numECBytesInBlock">The num EC bytes in block.</param>
internal static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes,
int numDataBytes,
int numRSBlocks,
int blockID,
int[] numDataBytesInBlock,
int[] numECBytesInBlock)
{
if (blockID >= numRSBlocks)
{
throw new Exception("Block ID too large");
}
// numRsBlocksInGroup2 = 196 % 5 = 1
int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;
// numRsBlocksInGroup1 = 5 - 1 = 4
int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;
// numTotalBytesInGroup1 = 196 / 5 = 39
int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks;
// numTotalBytesInGroup2 = 39 + 1 = 40
int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;
// numDataBytesInGroup1 = 66 / 5 = 13
int numDataBytesInGroup1 = numDataBytes / numRSBlocks;
// numDataBytesInGroup2 = 13 + 1 = 14
int numDataBytesInGroup2 = numDataBytesInGroup1 + 1;
// numEcBytesInGroup1 = 39 - 13 = 26
int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;
// numEcBytesInGroup2 = 40 - 14 = 26
int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;
// Sanity checks.
// 26 = 26
if (numEcBytesInGroup1 != numEcBytesInGroup2)
{
throw new Exception("EC bytes mismatch");
}
// 5 = 4 + 1.
if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2)
{
throw new Exception("RS blocks mismatch");
}
// 196 = (13 + 26) * 4 + (14 + 26) * 1
if (numTotalBytes !=
((numDataBytesInGroup1 + numEcBytesInGroup1) *
numRsBlocksInGroup1) +
((numDataBytesInGroup2 + numEcBytesInGroup2) *
numRsBlocksInGroup2))
{
throw new Exception("Total bytes mismatch");
}
if (blockID < numRsBlocksInGroup1)
{
numDataBytesInBlock[0] = numDataBytesInGroup1;
numECBytesInBlock[0] = numEcBytesInGroup1;
}
else
{
numDataBytesInBlock[0] = numDataBytesInGroup2;
numECBytesInBlock[0] = numEcBytesInGroup2;
}
}
/// <summary>
/// Interleave "bits" with corresponding error correction bytes. On success, store the result in
/// "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.
/// </summary>
/// <param name="bits">The bits.</param>
/// <param name="numTotalBytes">The num total bytes.</param>
/// <param name="numDataBytes">The num data bytes.</param>
/// <param name="numRSBlocks">The num RS blocks.</param>
/// <returns></returns>
internal static BitArray interleaveWithECBytes(BitArray bits,
int numTotalBytes,
int numDataBytes,
int numRSBlocks)
{
// "bits" must have "getNumDataBytes" bytes of data.
if (bits.SizeInBytes != numDataBytes)
{
throw new Exception("Number of bits and data bytes does not match");
}
// Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll
// store the divided data bytes blocks and error correction bytes blocks into "blocks".
int dataBytesOffset = 0;
int maxNumDataBytes = 0;
int maxNumEcBytes = 0;
// Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
var blocks = new List<BlockPair>(numRSBlocks);
for (int i = 0; i < numRSBlocks; ++i)
{
int[] numDataBytesInBlock = new int[1];
int[] numEcBytesInBlock = new int[1];
getNumDataBytesAndNumECBytesForBlockID(
numTotalBytes, numDataBytes, numRSBlocks, i,
numDataBytesInBlock, numEcBytesInBlock);
int size = numDataBytesInBlock[0];
byte[] dataBytes = new byte[size];
bits.toBytes(8 * dataBytesOffset, dataBytes, 0, size);
byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
blocks.Add(new BlockPair(dataBytes, ecBytes));
maxNumDataBytes = Math.Max(maxNumDataBytes, size);
maxNumEcBytes = Math.Max(maxNumEcBytes, ecBytes.Length);
dataBytesOffset += numDataBytesInBlock[0];
}
if (numDataBytes != dataBytesOffset)
{
throw new Exception("Data bytes does not match offset");
}
BitArray result = new BitArray();
// First, place data blocks.
for (int i = 0; i < maxNumDataBytes; ++i)
{
foreach (BlockPair block in blocks)
{
byte[] dataBytes = block.DataBytes;
if (i < dataBytes.Length)
{
result.appendBits(dataBytes[i], 8);
}
}
}
// Then, place error correction blocks.
for (int i = 0; i < maxNumEcBytes; ++i)
{
foreach (BlockPair block in blocks)
{
byte[] ecBytes = block.ErrorCorrectionBytes;
if (i < ecBytes.Length)
{
result.appendBits(ecBytes[i], 8);
}
}
}
if (numTotalBytes != result.SizeInBytes)
{ // Should be same.
throw new Exception("Interleaving error: " + numTotalBytes + " and " +
result.SizeInBytes + " differ.");
}
return result;
}
internal static byte[] generateECBytes(byte[] dataBytes, int numEcBytesInBlock)
{
int numDataBytes = dataBytes.Length;
int[] toEncode = new int[numDataBytes + numEcBytesInBlock];
for (int i = 0; i < numDataBytes; i++)
{
toEncode[i] = dataBytes[i] & 0xFF;
}
new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);
byte[] ecBytes = new byte[numEcBytesInBlock];
for (int i = 0; i < numEcBytesInBlock; i++)
{
ecBytes[i] = (byte)toEncode[numDataBytes + i];
}
return ecBytes;
}
/// <summary>
/// Append mode info. On success, store the result in "bits".
/// </summary>
/// <param name="mode">The mode.</param>
/// <param name="bits">The bits.</param>
internal static void appendModeInfo(Mode mode, BitArray bits)
{
bits.appendBits(mode.Bits, 4);
}
/// <summary>
/// Append length info. On success, store the result in "bits".
/// </summary>
/// <param name="numLetters">The num letters.</param>
/// <param name="version">The version.</param>
/// <param name="mode">The mode.</param>
/// <param name="bits">The bits.</param>
internal static void appendLengthInfo(int numLetters, Version version, Mode mode, BitArray bits)
{
int numBits = mode.getCharacterCountBits(version);
if (numLetters >= (1 << numBits))
{
throw new Exception(numLetters + " is bigger than " + ((1 << numBits) - 1));
}
bits.appendBits(numLetters, numBits);
}
/// <summary>
/// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits".
/// </summary>
/// <param name="content">The content.</param>
/// <param name="mode">The mode.</param>
/// <param name="bits">The bits.</param>
/// <param name="encoding">The encoding.</param>
internal static void appendBytes(String content,
Mode mode,
BitArray bits,
String encoding)
{
if (mode.Equals(Mode.BYTE))
append8BitBytes(content, bits, encoding);
else
throw new Exception("Invalid mode: " + mode);
}
internal static void append8BitBytes(String content, BitArray bits, String encoding)
{
byte[] bytes;
try
{
bytes = Encoding.GetEncoding(encoding).GetBytes(content);
}
#if WindowsCE
catch (PlatformNotSupportedException)
{
try
{
// WindowsCE doesn't support all encodings. But it is device depended.
// So we try here the some different ones
if (encoding == "ISO-8859-1")
{
bytes = Encoding.GetEncoding(1252).GetBytes(content);
}
else
{
bytes = Encoding.GetEncoding("UTF-8").GetBytes(content);
}
}
catch (Exception uee)
{
throw new WriterException(uee.Message, uee);
}
}
#endif
catch (Exception uee)
{
throw new Exception(uee.Message, uee);
}
foreach (byte b in bytes)
{
bits.appendBits(b, 8);
}
}
/*
private static void appendECI(CharacterSetECI eci, BitArray bits)
{
bits.appendBits(Mode.ECI.Bits, 4);
// This is correct for values up to 127, which is all we need now.
bits.appendBits(eci.Value, 8);
}
* */
}
}

+ 109
- 0
shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs View File

@@ -0,0 +1,109 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.QrCode.Internal
{
/// <summary>
/// <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels
/// defined by the QR code standard.</p>
/// </summary>
/// <author>Sean Owen</author>
public sealed class ErrorCorrectionLevel
{
/// <summary> L = ~7% correction</summary>
public static readonly ErrorCorrectionLevel L = new ErrorCorrectionLevel(0, 0x01, "L");
/// <summary> M = ~15% correction</summary>
public static readonly ErrorCorrectionLevel M = new ErrorCorrectionLevel(1, 0x00, "M");
/// <summary> Q = ~25% correction</summary>
public static readonly ErrorCorrectionLevel Q = new ErrorCorrectionLevel(2, 0x03, "Q");
/// <summary> H = ~30% correction</summary>
public static readonly ErrorCorrectionLevel H = new ErrorCorrectionLevel(3, 0x02, "H");
private static readonly ErrorCorrectionLevel[] FOR_BITS = new [] { M, L, H, Q };
private readonly int bits;
private ErrorCorrectionLevel(int ordinal, int bits, String name)
{
this.ordinal_Renamed_Field = ordinal;
this.bits = bits;
this.name = name;
}
/// <summary>
/// Gets the bits.
/// </summary>
public int Bits
{
get
{
return bits;
}
}
/// <summary>
/// Gets the name.
/// </summary>
public String Name
{
get
{
return name;
}
}
private readonly int ordinal_Renamed_Field;
private readonly String name;
/// <summary>
/// Ordinals this instance.
/// </summary>
/// <returns></returns>
public int ordinal()
{
return ordinal_Renamed_Field;
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override String ToString()
{
return name;
}
/// <summary>
/// Fors the bits.
/// </summary>
/// <param name="bits">int containing the two bits encoding a QR Code's error correction level</param>
/// <returns>
/// <see cref="ErrorCorrectionLevel"/> representing the encoded error correction level
/// </returns>
public static ErrorCorrectionLevel forBits(int bits)
{
if (bits < 0 || bits >= FOR_BITS.Length)
{
throw new ArgumentException();
}
return FOR_BITS[bits];
}
}
}

+ 163
- 0
shadowsocks-csharp/3rd/zxing/GenericGF.cs View File

@@ -0,0 +1,163 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.Common.ReedSolomon
{
/// <summary>
/// <p>This class contains utility methods for performing mathematical operations over
/// the Galois Fields. Operations use a given primitive polynomial in calculations.</p>
/// <p>Throughout this package, elements of the GF are represented as an {@code int}
/// for convenience and speed (but at the cost of memory).
/// </p>
/// </summary>
/// <author>Sean Owen</author>
public sealed class GenericGF
{
public static GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1
private int[] expTable;
private int[] logTable;
private GenericGFPoly zero;
private GenericGFPoly one;
private readonly int size;
private readonly int primitive;
private readonly int generatorBase;
/// <summary>
/// Create a representation of GF(size) using the given primitive polynomial.
/// </summary>
/// <param name="primitive">irreducible polynomial whose coefficients are represented by
/// * the bits of an int, where the least-significant bit represents the constant
/// * coefficient</param>
/// <param name="size">the size of the field</param>
/// <param name="genBase">the factor b in the generator polynomial can be 0- or 1-based
/// * (g(x) = (x+a^b)(x+a^(b+1))...(x+a^(b+2t-1))).
/// * In most cases it should be 1, but for QR code it is 0.</param>
public GenericGF(int primitive, int size, int genBase)
{
this.primitive = primitive;
this.size = size;
this.generatorBase = genBase;
expTable = new int[size];
logTable = new int[size];
int x = 1;
for (int i = 0; i < size; i++)
{
expTable[i] = x;
x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
if (x >= size)
{
x ^= primitive;
x &= size - 1;
}
}
for (int i = 0; i < size - 1; i++)
{
logTable[expTable[i]] = i;
}
// logTable[0] == 0 but this should never be used
zero = new GenericGFPoly(this, new int[] { 0 });
one = new GenericGFPoly(this, new int[] { 1 });
}
internal GenericGFPoly Zero
{
get
{
return zero;
}
}
/// <summary>
/// Builds the monomial.
/// </summary>
/// <param name="degree">The degree.</param>
/// <param name="coefficient">The coefficient.</param>
/// <returns>the monomial representing coefficient * x^degree</returns>
internal GenericGFPoly buildMonomial(int degree, int coefficient)
{
if (degree < 0)
{
throw new ArgumentException();
}
if (coefficient == 0)
{
return zero;
}
int[] coefficients = new int[degree + 1];
coefficients[0] = coefficient;
return new GenericGFPoly(this, coefficients);
}
/// <summary>
/// Implements both addition and subtraction -- they are the same in GF(size).
/// </summary>
/// <returns>sum/difference of a and b</returns>
static internal int addOrSubtract(int a, int b)
{
return a ^ b;
}
/// <summary>
/// Exps the specified a.
/// </summary>
/// <returns>2 to the power of a in GF(size)</returns>
internal int exp(int a)
{
return expTable[a];
}
/// <summary>
/// Inverses the specified a.
/// </summary>
/// <returns>multiplicative inverse of a</returns>
internal int inverse(int a)
{
if (a == 0)
{
throw new ArithmeticException();
}
return expTable[size - logTable[a] - 1];
}
/// <summary>
/// Multiplies the specified a with b.
/// </summary>
/// <param name="a">A.</param>
/// <param name="b">The b.</param>
/// <returns>product of a and b in GF(size)</returns>
internal int multiply(int a, int b)
{
if (a == 0 || b == 0)
{
return 0;
}
return expTable[(logTable[a] + logTable[b]) % (size - 1)];
}
/// <summary>
/// Gets the generator base.
/// </summary>
public int GeneratorBase
{
get { return generatorBase; }
}
}
}

+ 230
- 0
shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs View File

@@ -0,0 +1,230 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.Common.ReedSolomon
{
/// <summary>
/// <p>Represents a polynomial whose coefficients are elements of a GF.
/// Instances of this class are immutable.</p>
/// <p>Much credit is due to William Rucklidge since portions of this code are an indirect
/// port of his C++ Reed-Solomon implementation.</p>
/// </summary>
/// <author>Sean Owen</author>
internal sealed class GenericGFPoly
{
private readonly GenericGF field;
private readonly int[] coefficients;
/// <summary>
/// Initializes a new instance of the <see cref="GenericGFPoly"/> class.
/// </summary>
/// <param name="field">the {@link GenericGF} instance representing the field to use
/// to perform computations</param>
/// <param name="coefficients">coefficients as ints representing elements of GF(size), arranged
/// from most significant (highest-power term) coefficient to least significant</param>
/// <exception cref="ArgumentException">if argument is null or empty,
/// or if leading coefficient is 0 and this is not a
/// constant polynomial (that is, it is not the monomial "0")</exception>
internal GenericGFPoly(GenericGF field, int[] coefficients)
{
if (coefficients.Length == 0)
{
throw new ArgumentException();
}
this.field = field;
int coefficientsLength = coefficients.Length;
if (coefficientsLength > 1 && coefficients[0] == 0)
{
// Leading term must be non-zero for anything except the constant polynomial "0"
int firstNonZero = 1;
while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0)
{
firstNonZero++;
}
if (firstNonZero == coefficientsLength)
{
this.coefficients = new int[]{0};
}
else
{
this.coefficients = new int[coefficientsLength - firstNonZero];
Array.Copy(coefficients,
firstNonZero,
this.coefficients,
0,
this.coefficients.Length);
}
}
else
{
this.coefficients = coefficients;
}
}
internal int[] Coefficients
{
get { return coefficients; }
}
/// <summary>
/// degree of this polynomial
/// </summary>
internal int Degree
{
get
{
return coefficients.Length - 1;
}
}
/// <summary>
/// Gets a value indicating whether this <see cref="GenericGFPoly"/> is zero.
/// </summary>
/// <value>true iff this polynomial is the monomial "0"</value>
internal bool isZero
{
get { return coefficients[0] == 0; }
}
/// <summary>
/// coefficient of x^degree term in this polynomial
/// </summary>
/// <param name="degree">The degree.</param>
/// <returns>coefficient of x^degree term in this polynomial</returns>
internal int getCoefficient(int degree)
{
return coefficients[coefficients.Length - 1 - degree];
}
internal GenericGFPoly addOrSubtract(GenericGFPoly other)
{
if (!field.Equals(other.field))
{
throw new ArgumentException("GenericGFPolys do not have same GenericGF field");
}
if (isZero)
{
return other;
}
if (other.isZero)
{
return this;
}
int[] smallerCoefficients = this.coefficients;
int[] largerCoefficients = other.coefficients;
if (smallerCoefficients.Length > largerCoefficients.Length)
{
int[] temp = smallerCoefficients;
smallerCoefficients = largerCoefficients;
largerCoefficients = temp;
}
int[] sumDiff = new int[largerCoefficients.Length];
int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length;
// Copy high-order terms only found in higher-degree polynomial's coefficients
Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff);
for (int i = lengthDiff; i < largerCoefficients.Length; i++)
{
sumDiff[i] = GenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
}
return new GenericGFPoly(field, sumDiff);
}
internal GenericGFPoly multiply(GenericGFPoly other)
{
if (!field.Equals(other.field))
{
throw new ArgumentException("GenericGFPolys do not have same GenericGF field");
}
if (isZero || other.isZero)
{
return field.Zero;
}
int[] aCoefficients = this.coefficients;
int aLength = aCoefficients.Length;
int[] bCoefficients = other.coefficients;
int bLength = bCoefficients.Length;
int[] product = new int[aLength + bLength - 1];
for (int i = 0; i < aLength; i++)
{
int aCoeff = aCoefficients[i];
for (int j = 0; j < bLength; j++)
{
product[i + j] = GenericGF.addOrSubtract(product[i + j],
field.multiply(aCoeff, bCoefficients[j]));
}
}
return new GenericGFPoly(field, product);
}
internal GenericGFPoly multiplyByMonomial(int degree, int coefficient)
{
if (degree < 0)
{
throw new ArgumentException();
}
if (coefficient == 0)
{
return field.Zero;
}
int size = coefficients.Length;
int[] product = new int[size + degree];
for (int i = 0; i < size; i++)
{
product[i] = field.multiply(coefficients[i], coefficient);
}
return new GenericGFPoly(field, product);
}
internal GenericGFPoly[] divide(GenericGFPoly other)
{
if (!field.Equals(other.field))
{
throw new ArgumentException("GenericGFPolys do not have same GenericGF field");
}
if (other.isZero)
{
throw new ArgumentException("Divide by 0");
}
GenericGFPoly quotient = field.Zero;
GenericGFPoly remainder = this;
int denominatorLeadingTerm = other.getCoefficient(other.Degree);
int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);
while (remainder.Degree >= other.Degree && !remainder.isZero)
{
int degreeDifference = remainder.Degree - other.Degree;
int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm);
GenericGFPoly term = other.multiplyByMonomial(degreeDifference, scale);
GenericGFPoly iterationQuotient = field.buildMonomial(degreeDifference, scale);
quotient = quotient.addOrSubtract(iterationQuotient);
remainder = remainder.addOrSubtract(term);
}
return new GenericGFPoly[] { quotient, remainder };
}
}
}

+ 271
- 0
shadowsocks-csharp/3rd/zxing/MaskUtil.cs View File

@@ -0,0 +1,271 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.QrCode.Internal
{
/// <summary>
///
/// </summary>
/// <author>Satoru Takabayashi</author>
/// <author>Daniel Switkin</author>
/// <author>Sean Owen</author>
public static class MaskUtil
{
// Penalty weights from section 6.8.2.1
private const int N1 = 3;
private const int N2 = 3;
private const int N3 = 40;
private const int N4 = 10;
/// <summary>
/// Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and
/// give penalty to them. Example: 00000 or 11111.
/// </summary>
/// <param name="matrix">The matrix.</param>
/// <returns></returns>
public static int applyMaskPenaltyRule1(ByteMatrix matrix)
{
return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false);
}
/// <summary>
/// Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
/// penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a
/// penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.
/// </summary>
/// <param name="matrix">The matrix.</param>
/// <returns></returns>
public static int applyMaskPenaltyRule2(ByteMatrix matrix)
{
int penalty = 0;
var array = matrix.Array;
int width = matrix.Width;
int height = matrix.Height;
for (int y = 0; y < height - 1; y++)
{
for (int x = 0; x < width - 1; x++)
{
int value = array[y][x];
if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1])
{
penalty++;
}
}
}
return N2 * penalty;
}
/// <summary>
/// Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or
/// 10111010000, and give penalty to them. If we find patterns like 000010111010000, we give
/// penalties twice (i.e. 40 * 2).
/// </summary>
/// <param name="matrix">The matrix.</param>
/// <returns></returns>
public static int applyMaskPenaltyRule3(ByteMatrix matrix)
{
int numPenalties = 0;
byte[][] array = matrix.Array;
int width = matrix.Width;
int height = matrix.Height;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
byte[] arrayY = array[y]; // We can at least optimize this access
if (x + 6 < width &&
arrayY[x] == 1 &&
arrayY[x + 1] == 0 &&
arrayY[x + 2] == 1 &&
arrayY[x + 3] == 1 &&
arrayY[x + 4] == 1 &&
arrayY[x + 5] == 0 &&
arrayY[x + 6] == 1 &&
(isWhiteHorizontal(arrayY, x - 4, x) || isWhiteHorizontal(arrayY, x + 7, x + 11)))
{
numPenalties++;
}
if (y + 6 < height &&
array[y][x] == 1 &&
array[y + 1][x] == 0 &&
array[y + 2][x] == 1 &&
array[y + 3][x] == 1 &&
array[y + 4][x] == 1 &&
array[y + 5][x] == 0 &&
array[y + 6][x] == 1 &&
(isWhiteVertical(array, x, y - 4, y) || isWhiteVertical(array, x, y + 7, y + 11)))
{
numPenalties++;
}
}
}
return numPenalties * N3;
}
private static bool isWhiteHorizontal(byte[] rowArray, int from, int to)
{
for (int i = from; i < to; i++)
{
if (i >= 0 && i < rowArray.Length && rowArray[i] == 1)
{
return false;
}
}
return true;
}
private static bool isWhiteVertical(byte[][] array, int col, int from, int to)
{
for (int i = from; i < to; i++)
{
if (i >= 0 && i < array.Length && array[i][col] == 1)
{
return false;
}
}
return true;
}
/// <summary>
/// Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give
/// penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.
/// </summary>
/// <param name="matrix">The matrix.</param>
/// <returns></returns>
public static int applyMaskPenaltyRule4(ByteMatrix matrix)
{
int numDarkCells = 0;
var array = matrix.Array;
int width = matrix.Width;
int height = matrix.Height;
for (int y = 0; y < height; y++)
{
var arrayY = array[y];
for (int x = 0; x < width; x++)
{
if (arrayY[x] == 1)
{
numDarkCells++;
}
}
}
var numTotalCells = matrix.Height * matrix.Width;
var darkRatio = (double)numDarkCells / numTotalCells;
var fivePercentVariances = (int)(Math.Abs(darkRatio - 0.5) * 20.0); // * 100.0 / 5.0
return fivePercentVariances * N4;
}
/// <summary>
/// Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask
/// pattern conditions.
/// </summary>
/// <param name="maskPattern">The mask pattern.</param>
/// <param name="x">The x.</param>
/// <param name="y">The y.</param>
/// <returns></returns>
public static bool getDataMaskBit(int maskPattern, int x, int y)
{
int intermediate, temp;
switch (maskPattern)
{
case 0:
intermediate = (y + x) & 0x1;
break;
case 1:
intermediate = y & 0x1;
break;
case 2:
intermediate = x % 3;
break;
case 3:
intermediate = (y + x) % 3;
break;
case 4:
intermediate = (((int)((uint)y >> 1)) + (x / 3)) & 0x1;
break;
case 5:
temp = y * x;
intermediate = (temp & 0x1) + (temp % 3);
break;
case 6:
temp = y * x;
intermediate = (((temp & 0x1) + (temp % 3)) & 0x1);
break;
case 7:
temp = y * x;
intermediate = (((temp % 3) + ((y + x) & 0x1)) & 0x1);
break;
default:
throw new ArgumentException("Invalid mask pattern: " + maskPattern);
}
return intermediate == 0;
}
/// <summary>
/// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
/// vertical and horizontal orders respectively.
/// </summary>
/// <param name="matrix">The matrix.</param>
/// <param name="isHorizontal">if set to <c>true</c> [is horizontal].</param>
/// <returns></returns>
private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, bool isHorizontal)
{
int penalty = 0;
int iLimit = isHorizontal ? matrix.Height : matrix.Width;
int jLimit = isHorizontal ? matrix.Width : matrix.Height;
var array = matrix.Array;
for (int i = 0; i < iLimit; i++)
{
int numSameBitCells = 0;
int prevBit = -1;
for (int j = 0; j < jLimit; j++)
{
int bit = isHorizontal ? array[i][j] : array[j][i];
if (bit == prevBit)
{
numSameBitCells++;
}
else
{
if (numSameBitCells >= 5)
{
penalty += N1 + (numSameBitCells - 5);
}
numSameBitCells = 1; // Include the cell itself.
prevBit = bit;
}
}
if (numSameBitCells >= 5)
{
penalty += N1 + (numSameBitCells - 5);
}
}
return penalty;
}
}
}

+ 604
- 0
shadowsocks-csharp/3rd/zxing/MatrixUtil.cs View File

@@ -0,0 +1,604 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using ZXing.Common;
namespace ZXing.QrCode.Internal
{
/// <summary>
///
/// </summary>
/// <author>
/// satorux@google.com (Satoru Takabayashi) - creator
/// </author>
public static class MatrixUtil
{
private static readonly int[][] POSITION_DETECTION_PATTERN = new int[][]
{
new int[] { 1, 1, 1, 1, 1, 1, 1 },
new int[] { 1, 0, 0, 0, 0, 0, 1 },
new int[] { 1, 0, 1, 1, 1, 0, 1 },
new int[] { 1, 0, 1, 1, 1, 0, 1 },
new int[] { 1, 0, 1, 1, 1, 0, 1 },
new int[] { 1, 0, 0, 0, 0, 0, 1 },
new int[] { 1, 1, 1, 1, 1, 1, 1 }
};
private static readonly int[][] POSITION_ADJUSTMENT_PATTERN = new int[][]
{
new int[] { 1, 1, 1, 1, 1 },
new int[] { 1, 0, 0, 0, 1 },
new int[] { 1, 0, 1, 0, 1 },
new int[] { 1, 0, 0, 0, 1 },
new int[] { 1, 1, 1, 1, 1 }
};
// From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu.
private static readonly int[][] POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = new int[][]
{
new int[] { -1, -1, -1, -1, -1, -1, -1 },
new int[] { 6, 18, -1, -1, -1, -1, -1 },
new int[] { 6, 22, -1, -1, -1, -1, -1 },
new int[] { 6, 26, -1, -1, -1, -1, -1 },
new int[] { 6, 30, -1, -1, -1, -1, -1 },
new int[] { 6, 34, -1, -1, -1, -1, -1 },
new int[] { 6, 22, 38, -1, -1, -1, -1 },
new int[] { 6, 24, 42, -1, -1, -1, -1 },
new int[] { 6, 26, 46, -1, -1, -1, -1 },
new int[] { 6, 28, 50, -1, -1, -1, -1 },
new int[] { 6, 30, 54, -1, -1, -1, -1 },
new int[] { 6, 32, 58, -1, -1, -1, -1 },
new int[] { 6, 34, 62, -1, -1, -1, -1 },
new int[] { 6, 26, 46, 66, -1, -1, -1 },
new int[] { 6, 26, 48, 70, -1, -1, -1 },
new int[] { 6, 26, 50, 74, -1, -1, -1 },
new int[] { 6, 30, 54, 78, -1, -1, -1 },
new int[] { 6, 30, 56, 82, -1, -1, -1 },
new int[] { 6, 30, 58, 86, -1, -1, -1 },
new int[] { 6, 34, 62, 90, -1, -1, -1 },
new int[] { 6, 28, 50, 72, 94, -1, -1 },
new int[] { 6, 26, 50, 74, 98, -1, -1 },
new int[] { 6, 30, 54, 78, 102, -1, -1 },
new int[] { 6, 28, 54, 80, 106, -1, -1 },
new int[] { 6, 32, 58, 84, 110, -1, -1 },
new int[] { 6, 30, 58, 86, 114, -1, -1 },
new int[] { 6, 34, 62, 90, 118, -1, -1 },
new int[] { 6, 26, 50, 74, 98, 122, -1 },
new int[] { 6, 30, 54, 78, 102, 126, -1 },
new int[] { 6, 26, 52, 78, 104, 130, -1 },
new int[] { 6, 30, 56, 82, 108, 134, -1 },
new int[] { 6, 34, 60, 86, 112, 138, -1 },
new int[] { 6, 30, 58, 86, 114, 142, -1 },
new int[] { 6, 34, 62, 90, 118, 146, -1 },
new int[] { 6, 30, 54, 78, 102, 126, 150 },
new int[] { 6, 24, 50, 76, 102, 128, 154 },
new int[] { 6, 28, 54, 80, 106, 132, 158 },
new int[] { 6, 32, 58, 84, 110, 136, 162 },
new int[] { 6, 26, 54, 82, 110, 138, 166 },
new int[] { 6, 30, 58, 86, 114, 142, 170 }
};
// Type info cells at the left top corner.
private static readonly int[][] TYPE_INFO_COORDINATES = new int[][]
{
new int[] { 8, 0 },
new int[] { 8, 1 },
new int[] { 8, 2 },
new int[] { 8, 3 },
new int[] { 8, 4 },
new int[] { 8, 5 },
new int[] { 8, 7 },
new int[] { 8, 8 },
new int[] { 7, 8 },
new int[] { 5, 8 },
new int[] { 4, 8 },
new int[] { 3, 8 },
new int[] { 2, 8 },
new int[] { 1, 8 },
new int[] { 0, 8 }
};
// From Appendix D in JISX0510:2004 (p. 67)
private const int VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101
// From Appendix C in JISX0510:2004 (p.65).
private const int TYPE_INFO_POLY = 0x537;
private const int TYPE_INFO_MASK_PATTERN = 0x5412;
/// <summary>
/// Set all cells to 2. 2 means that the cell is empty (not set yet).
///
/// JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding
/// with the ByteMatrix initialized all to zero.
/// </summary>
/// <param name="matrix">The matrix.</param>
public static void clearMatrix(ByteMatrix matrix)
{
matrix.clear(2);
}
/// <summary>
/// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On
/// success, store the result in "matrix" and return true.
/// </summary>
/// <param name="dataBits">The data bits.</param>
/// <param name="ecLevel">The ec level.</param>
/// <param name="version">The version.</param>
/// <param name="maskPattern">The mask pattern.</param>
/// <param name="matrix">The matrix.</param>
public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, Version version, int maskPattern, ByteMatrix matrix)
{
clearMatrix(matrix);
embedBasicPatterns(version, matrix);
// Type information appear with any version.
embedTypeInfo(ecLevel, maskPattern, matrix);
// Version info appear if version >= 7.
maybeEmbedVersionInfo(version, matrix);
// Data should be embedded at end.
embedDataBits(dataBits, maskPattern, matrix);
}
/// <summary>
/// Embed basic patterns. On success, modify the matrix and return true.
/// The basic patterns are:
/// - Position detection patterns
/// - Timing patterns
/// - Dark dot at the left bottom corner
/// - Position adjustment patterns, if need be
/// </summary>
/// <param name="version">The version.</param>
/// <param name="matrix">The matrix.</param>
public static void embedBasicPatterns(Version version, ByteMatrix matrix)
{
// Let's get started with embedding big squares at corners.
embedPositionDetectionPatternsAndSeparators(matrix);
// Then, embed the dark dot at the left bottom corner.
embedDarkDotAtLeftBottomCorner(matrix);
// Position adjustment patterns appear if version >= 2.
maybeEmbedPositionAdjustmentPatterns(version, matrix);
// Timing patterns should be embedded after position adj. patterns.
embedTimingPatterns(matrix);
}
/// <summary>
/// Embed type information. On success, modify the matrix.
/// </summary>
/// <param name="ecLevel">The ec level.</param>
/// <param name="maskPattern">The mask pattern.</param>
/// <param name="matrix">The matrix.</param>
public static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix)
{
BitArray typeInfoBits = new BitArray();
makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);
for (int i = 0; i < typeInfoBits.Size; ++i)
{
// Place bits in LSB to MSB order. LSB (least significant bit) is the last value in
// "typeInfoBits".
int bit = typeInfoBits[typeInfoBits.Size - 1 - i] ? 1 : 0;
// Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
int x1 = TYPE_INFO_COORDINATES[i][0];
int y1 = TYPE_INFO_COORDINATES[i][1];
matrix[x1, y1] = bit;
if (i < 8)
{
// Right top corner.
int x2 = matrix.Width - i - 1;
int y2 = 8;
matrix[x2, y2] = bit;
}
else
{
// Left bottom corner.
int x2 = 8;
int y2 = matrix.Height - 7 + (i - 8);
matrix[x2, y2] = bit;
}
}
}
/// <summary>
/// Embed version information if need be. On success, modify the matrix and return true.
/// See 8.10 of JISX0510:2004 (p.47) for how to embed version information.
/// </summary>
/// <param name="version">The version.</param>
/// <param name="matrix">The matrix.</param>
public static void maybeEmbedVersionInfo(Version version, ByteMatrix matrix)
{
if (version.VersionNumber < 7)
{
// Version info is necessary if version >= 7.
return; // Don't need version info.
}
BitArray versionInfoBits = new BitArray();
makeVersionInfoBits(version, versionInfoBits);
int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.
for (int i = 0; i < 6; ++i)
{
for (int j = 0; j < 3; ++j)
{
// Place bits in LSB (least significant bit) to MSB order.
var bit = versionInfoBits[bitIndex] ? 1 : 0;
bitIndex--;
// Left bottom corner.
matrix[i, matrix.Height - 11 + j] = bit;
// Right bottom corner.
matrix[matrix.Height - 11 + j, i] = bit;
}
}
}
/// <summary>
/// Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true.
/// For debugging purposes, it skips masking process if "getMaskPattern" is -1.
/// See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
/// </summary>
/// <param name="dataBits">The data bits.</param>
/// <param name="maskPattern">The mask pattern.</param>
/// <param name="matrix">The matrix.</param>
public static void embedDataBits(BitArray dataBits, int maskPattern, ByteMatrix matrix)
{
int bitIndex = 0;
int direction = -1;
// Start from the right bottom cell.
int x = matrix.Width - 1;
int y = matrix.Height - 1;
while (x > 0)
{
// Skip the vertical timing pattern.
if (x == 6)
{
x -= 1;
}
while (y >= 0 && y < matrix.Height)
{
for (int i = 0; i < 2; ++i)
{
int xx = x - i;
// Skip the cell if it's not empty.
if (!isEmpty(matrix[xx, y]))
{
continue;
}
int bit;
if (bitIndex < dataBits.Size)
{
bit = dataBits[bitIndex] ? 1 : 0;
++bitIndex;
}
else
{
// Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
// in 8.4.9 of JISX0510:2004 (p. 24).
bit = 0;
}
// Skip masking if mask_pattern is -1.
if (maskPattern != -1)
{
if (MaskUtil.getDataMaskBit(maskPattern, xx, y))
{
bit ^= 0x1;
}
}
matrix[xx, y] = bit;
}
y += direction;
}
direction = -direction; // Reverse the direction.
y += direction;
x -= 2; // Move to the left.
}
// All bits should be consumed.
if (bitIndex != dataBits.Size)
{
throw new Exception("Not all bits consumed: " + bitIndex + '/' + dataBits.Size);
}
}
/// <summary>
/// Return the position of the most significant bit set (to one) in the "value". The most
/// significant bit is position 32. If there is no bit set, return 0. Examples:
/// - findMSBSet(0) => 0
/// - findMSBSet(1) => 1
/// - findMSBSet(255) => 8
/// </summary>
/// <param name="value_Renamed">The value_ renamed.</param>
/// <returns></returns>
public static int findMSBSet(int value_Renamed)
{
int numDigits = 0;
while (value_Renamed != 0)
{
value_Renamed = (int)((uint)value_Renamed >> 1);
++numDigits;
}
return numDigits;
}
/// <summary>
/// Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH
/// code is used for encoding type information and version information.
/// Example: Calculation of version information of 7.
/// f(x) is created from 7.
/// - 7 = 000111 in 6 bits
/// - f(x) = x^2 + x^2 + x^1
/// g(x) is given by the standard (p. 67)
/// - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1
/// Multiply f(x) by x^(18 - 6)
/// - f'(x) = f(x) * x^(18 - 6)
/// - f'(x) = x^14 + x^13 + x^12
/// Calculate the remainder of f'(x) / g(x)
/// x^2
/// __________________________________________________
/// g(x) )x^14 + x^13 + x^12
/// x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2
/// --------------------------------------------------
/// x^11 + x^10 + x^7 + x^4 + x^2
///
/// The remainder is x^11 + x^10 + x^7 + x^4 + x^2
/// Encode it in binary: 110010010100
/// The return value is 0xc94 (1100 1001 0100)
///
/// Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit
/// operations. We don't care if cofficients are positive or negative.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="poly">The poly.</param>
/// <returns></returns>
public static int calculateBCHCode(int value, int poly)
{
if (poly == 0)
throw new ArgumentException("0 polynominal", "poly");
// If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1
// from 13 to make it 12.
int msbSetInPoly = findMSBSet(poly);
value <<= msbSetInPoly - 1;
// Do the division business using exclusive-or operations.
while (findMSBSet(value) >= msbSetInPoly)
{
value ^= poly << (findMSBSet(value) - msbSetInPoly);
}
// Now the "value" is the remainder (i.e. the BCH code)
return value;
}
/// <summary>
/// Make bit vector of type information. On success, store the result in "bits" and return true.
/// Encode error correction level and mask pattern. See 8.9 of
/// JISX0510:2004 (p.45) for details.
/// </summary>
/// <param name="ecLevel">The ec level.</param>
/// <param name="maskPattern">The mask pattern.</param>
/// <param name="bits">The bits.</param>
public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits)
{
if (!QRCode.isValidMaskPattern(maskPattern))
{
throw new Exception("Invalid mask pattern");
}
int typeInfo = (ecLevel.Bits << 3) | maskPattern;
bits.appendBits(typeInfo, 5);
int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY);
bits.appendBits(bchCode, 10);
BitArray maskBits = new BitArray();
maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15);
bits.xor(maskBits);
if (bits.Size != 15)
{
// Just in case.
throw new Exception("should not happen but we got: " + bits.Size);
}
}
/// <summary>
/// Make bit vector of version information. On success, store the result in "bits" and return true.
/// See 8.10 of JISX0510:2004 (p.45) for details.
/// </summary>
/// <param name="version">The version.</param>
/// <param name="bits">The bits.</param>
public static void makeVersionInfoBits(Version version, BitArray bits)
{
bits.appendBits(version.VersionNumber, 6);
int bchCode = calculateBCHCode(version.VersionNumber, VERSION_INFO_POLY);
bits.appendBits(bchCode, 12);
if (bits.Size != 18)
{
// Just in case.
throw new Exception("should not happen but we got: " + bits.Size);
}
}
/// <summary>
/// Check if "value" is empty.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>
/// <c>true</c> if the specified value is empty; otherwise, <c>false</c>.
/// </returns>
private static bool isEmpty(int value)
{
return value == 2;
}
private static void embedTimingPatterns(ByteMatrix matrix)
{
// -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
// separation patterns (size 1). Thus, 8 = 7 + 1.
for (int i = 8; i < matrix.Width - 8; ++i)
{
int bit = (i + 1) % 2;
// Horizontal line.
if (isEmpty(matrix[i, 6]))
{
matrix[i, 6] = bit;
}
// Vertical line.
if (isEmpty(matrix[6, i]))
{
matrix[6, i] = bit;
}
}
}
/// <summary>
/// Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)
/// </summary>
/// <param name="matrix">The matrix.</param>
private static void embedDarkDotAtLeftBottomCorner(ByteMatrix matrix)
{
if (matrix[8, matrix.Height - 8] == 0)
{
throw new Exception();
}
matrix[8, matrix.Height - 8] = 1;
}
private static void embedHorizontalSeparationPattern(int xStart, int yStart, ByteMatrix matrix)
{
for (int x = 0; x < 8; ++x)
{
if (!isEmpty(matrix[xStart + x, yStart]))
{
throw new Exception();
}
matrix[xStart + x, yStart] = 0;
}
}
private static void embedVerticalSeparationPattern(int xStart, int yStart, ByteMatrix matrix)
{
for (int y = 0; y < 7; ++y)
{
if (!isEmpty(matrix[xStart, yStart + y]))
{
throw new Exception();
}
matrix[xStart, yStart + y] = 0;
}
}
/// <summary>
/// Note that we cannot unify the function with embedPositionDetectionPattern() despite they are
/// almost identical, since we cannot write a function that takes 2D arrays in different sizes in
/// C/C++. We should live with the fact.
/// </summary>
/// <param name="xStart">The x start.</param>
/// <param name="yStart">The y start.</param>
/// <param name="matrix">The matrix.</param>
private static void embedPositionAdjustmentPattern(int xStart, int yStart, ByteMatrix matrix)
{
for (int y = 0; y < 5; ++y)
{
for (int x = 0; x < 5; ++x)
{
matrix[xStart + x, yStart + y] = POSITION_ADJUSTMENT_PATTERN[y][x];
}
}
}
private static void embedPositionDetectionPattern(int xStart, int yStart, ByteMatrix matrix)
{
for (int y = 0; y < 7; ++y)
{
for (int x = 0; x < 7; ++x)
{
matrix[xStart + x, yStart + y] = POSITION_DETECTION_PATTERN[y][x];
}
}
}
/// <summary>
/// Embed position detection patterns and surrounding vertical/horizontal separators.
/// </summary>
/// <param name="matrix">The matrix.</param>
private static void embedPositionDetectionPatternsAndSeparators(ByteMatrix matrix)
{
// Embed three big squares at corners.
int pdpWidth = POSITION_DETECTION_PATTERN[0].Length;
// Left top corner.
embedPositionDetectionPattern(0, 0, matrix);
// Right top corner.
embedPositionDetectionPattern(matrix.Width - pdpWidth, 0, matrix);
// Left bottom corner.
embedPositionDetectionPattern(0, matrix.Width - pdpWidth, matrix);
// Embed horizontal separation patterns around the squares.
const int hspWidth = 8;
// Left top corner.
embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);
// Right top corner.
embedHorizontalSeparationPattern(matrix.Width - hspWidth, hspWidth - 1, matrix);
// Left bottom corner.
embedHorizontalSeparationPattern(0, matrix.Width - hspWidth, matrix);
// Embed vertical separation patterns around the squares.
const int vspSize = 7;
// Left top corner.
embedVerticalSeparationPattern(vspSize, 0, matrix);
// Right top corner.
embedVerticalSeparationPattern(matrix.Height - vspSize - 1, 0, matrix);
// Left bottom corner.
embedVerticalSeparationPattern(vspSize, matrix.Height - vspSize, matrix);
}
/// <summary>
/// Embed position adjustment patterns if need be.
/// </summary>
/// <param name="version">The version.</param>
/// <param name="matrix">The matrix.</param>
private static void maybeEmbedPositionAdjustmentPatterns(Version version, ByteMatrix matrix)
{
if (version.VersionNumber < 2)
{
// The patterns appear if version >= 2
return;
}
int index = version.VersionNumber - 1;
int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];
int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].Length;
for (int i = 0; i < numCoordinates; ++i)
{
for (int j = 0; j < numCoordinates; ++j)
{
int y = coordinates[i];
int x = coordinates[j];
if (x == -1 || y == -1)
{
continue;
}
// If the cell is unset, we embed the position adjustment pattern here.
if (isEmpty(matrix[x, y]))
{
// -2 is necessary since the x/y coordinates point to the center of the pattern, not the
// left top corner.
embedPositionAdjustmentPattern(x - 2, y - 2, matrix);
}
}
}
}
}
}

+ 115
- 0
shadowsocks-csharp/3rd/zxing/Mode.cs View File

@@ -0,0 +1,115 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace ZXing.QrCode.Internal
{
/// <summary>
/// <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which
/// data can be encoded to bits in the QR code standard.</p>
/// </summary>
/// <author>Sean Owen</author>
public sealed class Mode
{
/// <summary>
/// Gets the name.
/// </summary>
public String Name
{
get
{
return name;
}
}
// No, we can't use an enum here. J2ME doesn't support it.
/// <summary>
///
/// </summary>
public static readonly Mode BYTE = new Mode(new int[] { 8, 16, 16 }, 0x04, "BYTE");
private readonly int[] characterCountBitsForVersions;
private readonly int bits;
private readonly String name;
private Mode(int[] characterCountBitsForVersions, int bits, System.String name)
{
this.characterCountBitsForVersions = characterCountBitsForVersions;
this.bits = bits;
this.name = name;
}
/// <summary>
/// Fors the bits.
/// </summary>
/// <param name="bits">four bits encoding a QR Code data mode</param>
/// <returns>
/// <see cref="Mode"/> encoded by these bits
/// </returns>
/// <exception cref="ArgumentException">if bits do not correspond to a known mode</exception>
public static Mode forBits(int bits)
{
switch (bits)
{
case 0x4:
return BYTE;
default:
throw new ArgumentException();
}
}
/// <param name="version">version in question
/// </param>
/// <returns> number of bits used, in this QR Code symbol {@link Version}, to encode the
/// count of characters that will follow encoded in this {@link Mode}
/// </returns>
public int getCharacterCountBits(Version version)
{
if (characterCountBitsForVersions == null)
{
throw new ArgumentException("Character count doesn't apply to this mode");
}
int number = version.VersionNumber;
int offset;
if (number <= 9)
{
offset = 0;
}
else if (number <= 26)
{
offset = 1;
}
else
{
offset = 2;
}
return characterCountBitsForVersions[offset];
}
/// <summary>
/// Gets the bits.
/// </summary>
public int Bits
{
get
{
return bits;
}
}
}
}

+ 91
- 0
shadowsocks-csharp/3rd/zxing/QRCode.cs View File

@@ -0,0 +1,91 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Text;
namespace ZXing.QrCode.Internal
{
/// <author>satorux@google.com (Satoru Takabayashi) - creator</author>
/// <author>dswitkin@google.com (Daniel Switkin) - ported from C++</author>
public class QRCode
{
/// <summary>
///
/// </summary>
public static int NUM_MASK_PATTERNS = 8;
/// <summary>
/// Initializes a new instance of the <see cref="QRCode"/> class.
/// </summary>
public QRCode()
{
MaskPattern = -1;
}
/// <summary>
/// Gets or sets the mode.
/// </summary>
/// <value>
/// The mode.
/// </value>
public Mode Mode { get; set; }
/// <summary>
/// Gets or sets the EC level.
/// </summary>
/// <value>
/// The EC level.
/// </value>
public ErrorCorrectionLevel ECLevel { get; set; }
/// <summary>
/// Gets or sets the version.
/// </summary>
/// <value>
/// The version.
/// </value>
public Version Version { get; set; }
/// <summary>
/// Gets or sets the mask pattern.
/// </summary>
/// <value>
/// The mask pattern.
/// </value>
public int MaskPattern { get; set; }
/// <summary>
/// Gets or sets the matrix.
/// </summary>
/// <value>
/// The matrix.
/// </value>
public ByteMatrix Matrix { get; set; }
/// <summary>
/// Check if "mask_pattern" is valid.
/// </summary>
/// <param name="maskPattern">The mask pattern.</param>
/// <returns>
/// <c>true</c> if [is valid mask pattern] [the specified mask pattern]; otherwise, <c>false</c>.
/// </returns>
public static bool isValidMaskPattern(int maskPattern)
{
return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
}
}
}

+ 84
- 0
shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs View File

@@ -0,0 +1,84 @@
/*
* Copyright 2008 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
namespace ZXing.Common.ReedSolomon
{
/// <summary>
/// Implements Reed-Solomon encoding, as the name implies.
/// </summary>
/// <author>Sean Owen</author>
/// <author>William Rucklidge</author>
public sealed class ReedSolomonEncoder
{
private readonly GenericGF field;
private readonly IList<GenericGFPoly> cachedGenerators;
public ReedSolomonEncoder(GenericGF field)
{
this.field = field;
this.cachedGenerators = new List<GenericGFPoly>();
cachedGenerators.Add(new GenericGFPoly(field, new int[] { 1 }));
}
private GenericGFPoly buildGenerator(int degree)
{
if (degree >= cachedGenerators.Count)
{
var lastGenerator = cachedGenerators[cachedGenerators.Count - 1];
for (int d = cachedGenerators.Count; d <= degree; d++)
{
var nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, new int[] { 1, field.exp(d - 1 + field.GeneratorBase) }));
cachedGenerators.Add(nextGenerator);
lastGenerator = nextGenerator;
}
}
return cachedGenerators[degree];
}
public void encode(int[] toEncode, int ecBytes)
{
if (ecBytes == 0)
{
throw new ArgumentException("No error correction bytes");
}
var dataBytes = toEncode.Length - ecBytes;
if (dataBytes <= 0)
{
throw new ArgumentException("No data bytes provided");
}
var generator = buildGenerator(ecBytes);
var infoCoefficients = new int[dataBytes];
Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes);
var info = new GenericGFPoly(field, infoCoefficients);
info = info.multiplyByMonomial(ecBytes, 1);
var remainder = info.divide(generator)[1];
var coefficients = remainder.Coefficients;
var numZeroCoefficients = ecBytes - coefficients.Length;
for (var i = 0; i < numZeroCoefficients; i++)
{
toEncode[dataBytes + i] = 0;
}
Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length);
}
}
}

+ 342
- 0
shadowsocks-csharp/3rd/zxing/Version.cs View File

@@ -0,0 +1,342 @@
/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using ZXing.Common;
namespace ZXing.QrCode.Internal
{
/// <summary>
/// See ISO 18004:2006 Annex D
/// </summary>
/// <author>Sean Owen</author>
public sealed class Version
{
private static readonly Version[] VERSIONS = buildVersions();
private readonly int versionNumber;
private readonly int[] alignmentPatternCenters;
private readonly ECBlocks[] ecBlocks;
private readonly int totalCodewords;
private Version(int versionNumber, int[] alignmentPatternCenters, params ECBlocks[] ecBlocks)
{
this.versionNumber = versionNumber;
this.alignmentPatternCenters = alignmentPatternCenters;
this.ecBlocks = ecBlocks;
int total = 0;
int ecCodewords = ecBlocks[0].ECCodewordsPerBlock;
ECB[] ecbArray = ecBlocks[0].getECBlocks();
foreach (var ecBlock in ecbArray)
{
total += ecBlock.Count * (ecBlock.DataCodewords + ecCodewords);
}
this.totalCodewords = total;
}
/// <summary>
/// Gets the version number.
/// </summary>
public int VersionNumber
{
get
{
return versionNumber;
}
}
/// <summary>
/// Gets the total codewords.
/// </summary>
public int TotalCodewords
{
get
{
return totalCodewords;
}
}
/// <summary>
/// Gets the dimension for version.
/// </summary>
public int DimensionForVersion
{
get
{
return 17 + 4 * versionNumber;
}
}
/// <summary>
/// Gets the EC blocks for level.
/// </summary>
/// <param name="ecLevel">The ec level.</param>
/// <returns></returns>
public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel)
{
return ecBlocks[ecLevel.ordinal()];
}
/// <summary>
/// Gets the version for number.
/// </summary>
/// <param name="versionNumber">The version number.</param>
/// <returns></returns>
public static Version getVersionForNumber(int versionNumber)
{
if (versionNumber < 1 || versionNumber > 40)
{
throw new ArgumentException();
}
return VERSIONS[versionNumber - 1];
}
/// <summary> <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
/// use blocks of differing sizes within one version, so, this encapsulates the parameters for
/// each set of blocks. It also holds the number of error-correction codewords per block since it
/// will be the same across all blocks within one version.</p>
/// </summary>
public sealed class ECBlocks
{
private readonly int ecCodewordsPerBlock;
private readonly ECB[] ecBlocks;
internal ECBlocks(int ecCodewordsPerBlock, params ECB[] ecBlocks)
{
this.ecCodewordsPerBlock = ecCodewordsPerBlock;
this.ecBlocks = ecBlocks;
}
/// <summary>
/// Gets the EC codewords per block.
/// </summary>
public int ECCodewordsPerBlock
{
get
{
return ecCodewordsPerBlock;
}
}
/// <summary>
/// Gets the num blocks.
/// </summary>
public int NumBlocks
{
get
{
int total = 0;
foreach (var ecBlock in ecBlocks)
{
total += ecBlock.Count;
}
return total;
}
}
/// <summary>
/// Gets the total EC codewords.
/// </summary>
public int TotalECCodewords
{
get
{
return ecCodewordsPerBlock * NumBlocks;
}
}
/// <summary>
/// Gets the EC blocks.
/// </summary>
/// <returns></returns>
public ECB[] getECBlocks()
{
return ecBlocks;
}
}
/// <summary> <p>Encapsualtes the parameters for one error-correction block in one symbol version.
/// This includes the number of data codewords, and the number of times a block with these
/// parameters is used consecutively in the QR code version's format.</p>
/// </summary>
public sealed class ECB
{
private readonly int count;
private readonly int dataCodewords;
internal ECB(int count, int dataCodewords)
{
this.count = count;
this.dataCodewords = dataCodewords;
}
/// <summary>
/// Gets the count.
/// </summary>
public int Count
{
get
{
return count;
}
}
/// <summary>
/// Gets the data codewords.
/// </summary>
public int DataCodewords
{
get
{
return dataCodewords;
}
}
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public override String ToString()
{
return Convert.ToString(versionNumber);
}
/// <summary> See ISO 18004:2006 6.5.1 Table 9</summary>
private static Version[] buildVersions()
{
return new Version[]
{
new Version(1, new int[] {},
new ECBlocks(7, new ECB(1, 19)),
new ECBlocks(10, new ECB(1, 16)),
new ECBlocks(13, new ECB(1, 13)),
new ECBlocks(17, new ECB(1, 9))),
new Version(2, new int[] {6, 18},
new ECBlocks(10, new ECB(1, 34)),
new ECBlocks(16, new ECB(1, 28)),
new ECBlocks(22, new ECB(1, 22)),
new ECBlocks(28, new ECB(1, 16))),
new Version(3, new int[] {6, 22},
new ECBlocks(15, new ECB(1, 55)),
new ECBlocks(26, new ECB(1, 44)),
new ECBlocks(18, new ECB(2, 17)),
new ECBlocks(22, new ECB(2, 13))),
new Version(4, new int[] {6, 26},
new ECBlocks(20, new ECB(1, 80)),
new ECBlocks(18, new ECB(2, 32)),
new ECBlocks(26, new ECB(2, 24)),
new ECBlocks(16, new ECB(4, 9))),
new Version(5, new int[] {6, 30},
new ECBlocks(26, new ECB(1, 108)),
new ECBlocks(24, new ECB(2, 43)),
new ECBlocks(18, new ECB(2, 15),
new ECB(2, 16)),
new ECBlocks(22, new ECB(2, 11),
new ECB(2, 12))),
new Version(6, new int[] {6, 34},
new ECBlocks(18, new ECB(2, 68)),
new ECBlocks(16, new ECB(4, 27)),
new ECBlocks(24, new ECB(4, 19)),
new ECBlocks(28, new ECB(4, 15))),
new Version(7, new int[] {6, 22, 38},
new ECBlocks(20, new ECB(2, 78)),
new ECBlocks(18, new ECB(4, 31)),
new ECBlocks(18, new ECB(2, 14),
new ECB(4, 15)),
new ECBlocks(26, new ECB(4, 13),
new ECB(1, 14))),
new Version(8, new int[] {6, 24, 42},
new ECBlocks(24, new ECB(2, 97)),
new ECBlocks(22, new ECB(2, 38),
new ECB(2, 39)),
new ECBlocks(22, new ECB(4, 18),
new ECB(2, 19)),
new ECBlocks(26, new ECB(4, 14),
new ECB(2, 15))),
new Version(9, new int[] {6, 26, 46},
new ECBlocks(30, new ECB(2, 116)),
new ECBlocks(22, new ECB(3, 36),
new ECB(2, 37)),
new ECBlocks(20, new ECB(4, 16),
new ECB(4, 17)),
new ECBlocks(24, new ECB(4, 12),
new ECB(4, 13))),
new Version(10, new int[] {6, 28, 50},
new ECBlocks(18, new ECB(2, 68),
new ECB(2, 69)),
new ECBlocks(26, new ECB(4, 43),
new ECB(1, 44)),
new ECBlocks(24, new ECB(6, 19),
new ECB(2, 20)),
new ECBlocks(28, new ECB(6, 15),
new ECB(2, 16))),
new Version(11, new int[] {6, 30, 54},
new ECBlocks(20, new ECB(4, 81)),
new ECBlocks(30, new ECB(1, 50),
new ECB(4, 51)),
new ECBlocks(28, new ECB(4, 22),
new ECB(4, 23)),
new ECBlocks(24, new ECB(3, 12),
new ECB(8, 13))),
new Version(12, new int[] {6, 32, 58},
new ECBlocks(24, new ECB(2, 92),
new ECB(2, 93)),
new ECBlocks(22, new ECB(6, 36),
new ECB(2, 37)),
new ECBlocks(26, new ECB(4, 20),
new ECB(6, 21)),
new ECBlocks(28, new ECB(7, 14),
new ECB(4, 15))),
new Version(13, new int[] {6, 34, 62},
new ECBlocks(26, new ECB(4, 107)),
new ECBlocks(22, new ECB(8, 37),
new ECB(1, 38)),
new ECBlocks(24, new ECB(8, 20),
new ECB(4, 21)),
new ECBlocks(22, new ECB(12, 11),
new ECB(4, 12))),
new Version(14, new int[] {6, 26, 46, 66},
new ECBlocks(30, new ECB(3, 115),
new ECB(1, 116)),
new ECBlocks(24, new ECB(4, 40),
new ECB(5, 41)),
new ECBlocks(20, new ECB(11, 16),
new ECB(5, 17)),
new ECBlocks(24, new ECB(11, 12),
new ECB(5, 13))),
new Version(15, new int[] {6, 26, 48, 70},
new ECBlocks(22, new ECB(5, 87),
new ECB(1, 88)),
new ECBlocks(24, new ECB(5, 41),
new ECB(5, 42)),
new ECBlocks(30, new ECB(5, 24),
new ECB(7, 25)),
new ECBlocks(24, new ECB(11, 12),
new ECB(7, 13)))
};
}
}
}

+ 52
- 36
shadowsocks-csharp/Controller/AutoStartup.cs View File

@@ -1,39 +1,55 @@
using System;
using System.Windows.Forms;
using Microsoft.Win32;

namespace Shadowsocks.Controller {
class AutoStartup {
public static bool Set(bool enabled) {
try {
string path = Application.ExecutablePath;
RegistryKey runKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (enabled) {
runKey.SetValue("Shadowsocks", path);
} else {
runKey.DeleteValue("Shadowsocks");
}
runKey.Close();
return true;
} catch (Exception) {
return false;
}
}

public static bool Check() {
try {
string path = Application.ExecutablePath;
RegistryKey runKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
string[] runList = runKey.GetValueNames();
runKey.Close();
foreach (string item in runList) {
if (item.Equals("Shadowsocks"))
return true;
}
return false;
} catch (Exception) {
return false;
}
}
}
using Microsoft.Win32;
namespace Shadowsocks.Controller
{
class AutoStartup
{
public static bool Set(bool enabled)
{
try
{
string path = Application.ExecutablePath;
RegistryKey runKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
if (enabled)
{
runKey.SetValue("Shadowsocks", path);
}
else
{
runKey.DeleteValue("Shadowsocks");
}
runKey.Close();
return true;
}
catch (Exception e)
{
Logging.LogUsefulException(e);
return false;
}
}
public static bool Check()
{
try
{
string path = Application.ExecutablePath;
RegistryKey runKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
string[] runList = runKey.GetValueNames();
runKey.Close();
foreach (string item in runList)
{
if (item.Equals("Shadowsocks"))
return true;
}
return false;
}
catch (Exception e)
{
Logging.LogUsefulException(e);
return false;
}
}
}
}

+ 1
- 1
shadowsocks-csharp/Controller/Local.cs View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using Shadowsocks.Encrypt;
using Shadowsocks.Encryption;
using Shadowsocks.Model;
namespace Shadowsocks.Controller


+ 26
- 2
shadowsocks-csharp/Controller/Logging.cs View File

@@ -17,8 +17,7 @@ namespace Shadowsocks.Controller
string temppath = Path.GetTempPath();
LogFile = Path.Combine(temppath, "shadowsocks.log");
FileStream fs = new FileStream(LogFile, FileMode.Append);
TextWriter tmp = Console.Out;
StreamWriter sw = new StreamWriter(fs);
StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs);
sw.AutoFlush = true;
Console.SetOut(sw);
Console.SetError(sw);
@@ -61,5 +60,30 @@ namespace Shadowsocks.Controller
Console.WriteLine(e);
}
}
}
// Simply extended System.IO.StreamWriter for adding timestamp workaround
public class StreamWriterWithTimestamp : StreamWriter
{
public StreamWriterWithTimestamp(Stream stream) : base(stream)
{
}
private string GetTimestamp()
{
return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] ";
}
public override void WriteLine(string value)
{
base.WriteLine(GetTimestamp() + value);
}
public override void Write(string value)
{
base.Write(GetTimestamp() + value);
}
}
}

+ 2
- 2
shadowsocks-csharp/Controller/UpdateChecker.cs View File

@@ -17,7 +17,7 @@ namespace Shadowsocks.Controller
public string LatestVersionURL;
public event EventHandler NewVersionFound;
public const string Version = "2.1.4";
public const string Version = "2.1.6";
public void CheckUpdate()
{
@@ -145,7 +145,7 @@ namespace Shadowsocks.Controller
}
catch (Exception ex)
{
Console.Write(ex.ToString());
Console.WriteLine(ex.ToString());
return;
}
}


+ 1
- 1
shadowsocks-csharp/Data/cn.txt View File

@@ -5,7 +5,7 @@ PAC=PAC 模式
Global=全局模式
Servers=服务器选择
Edit Servers...=编辑服务器...
Start on Boot=自动启动
Start on Boot=开机启动
Share over LAN=在局域网共享代理
Edit PAC File...=编辑 PAC 文件...
Show QRCode...=显示二维码...


BIN
shadowsocks-csharp/Data/polipo.exe.gz View File


shadowsocks-csharp/Encrypt/EncryptorBase.cs → shadowsocks-csharp/Encryption/EncryptorBase.cs View File

@@ -1,7 +1,7 @@
using System.Security.Cryptography;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public abstract class EncryptorBase
: IEncryptor

shadowsocks-csharp/Encrypt/EncryptorFactory.cs → shadowsocks-csharp/Encryption/EncryptorFactory.cs View File

@@ -2,7 +2,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public static class EncryptorFactory
{

shadowsocks-csharp/Encrypt/IEncryptor.cs → shadowsocks-csharp/Encryption/IEncryptor.cs View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public interface IEncryptor : IDisposable
{

shadowsocks-csharp/Encrypt/IVEncryptor.cs → shadowsocks-csharp/Encryption/IVEncryptor.cs View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public abstract class IVEncryptor
: EncryptorBase

shadowsocks-csharp/Encrypt/PolarSSL.cs → shadowsocks-csharp/Encryption/PolarSSL.cs View File

@@ -6,7 +6,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public class PolarSSL
{

shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs → shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs View File

@@ -5,7 +5,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public class PolarSSLEncryptor
: IVEncryptor, IDisposable

shadowsocks-csharp/Encrypt/Sodium.cs → shadowsocks-csharp/Encryption/Sodium.cs View File

@@ -6,7 +6,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public class Sodium
{

shadowsocks-csharp/Encrypt/SodiumEncryptor.cs → shadowsocks-csharp/Encryption/SodiumEncryptor.cs View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public class SodiumEncryptor
: IVEncryptor, IDisposable

shadowsocks-csharp/Encrypt/TableEncryptor.cs → shadowsocks-csharp/Encryption/TableEncryptor.cs View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace Shadowsocks.Encrypt
namespace Shadowsocks.Encryption
{
public class TableEncryptor
: EncryptorBase

+ 1
- 1
shadowsocks-csharp/Properties/AssemblyInfo.cs View File

@@ -11,7 +11,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Shadowsocks")]
[assembly: AssemblyCopyright("Copyright © clowwindy 2014")]
[assembly: AssemblyCopyright("Copyright © clowwindy 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]


+ 0
- 26
shadowsocks-csharp/Properties/Settings.Designer.cs View File

@@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18444
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Shadowsocks.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

+ 0
- 7
shadowsocks-csharp/Properties/Settings.settings View File

@@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

+ 39
- 152
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -28,16 +28,7 @@ namespace Shadowsocks.View
private MenuItem ShareOverLANItem;
private MenuItem SeperatorItem;
private MenuItem ConfigItem;
private MenuItem menuItem4;
private MenuItem editPACFileItem;
private MenuItem QRCodeItem;
private MenuItem ShowLogItem;
private MenuItem aboutItem;
private MenuItem ServersItem;
private MenuItem menuItem3;
private MenuItem quitItem;
private MenuItem menuItem1;
private MenuItem modeItem;
private MenuItem globalModeItem;
private MenuItem PACModeItem;
private ConfigForm configForm;
@@ -59,7 +50,7 @@ namespace Shadowsocks.View
UpdateTrayIcon();
_notifyIcon.Visible = true;
_notifyIcon.ContextMenu = contextMenu1;
_notifyIcon.DoubleClick += notifyIcon1_DoubleClick;
_notifyIcon.MouseDoubleClick += notifyIcon1_DoubleClick;
this.updateChecker = new UpdateChecker();
updateChecker.NewVersionFound += updateChecker_NewVersionFound;
@@ -121,146 +112,39 @@ namespace Shadowsocks.View
_notifyIcon.Text = text.Substring(0, Math.Min(63, text.Length));
}
private MenuItem CreateMenuItem(string text, EventHandler click)
{
return new MenuItem(I18N.GetString(text), click);
}
private MenuItem CreateMenuGroup(string text, MenuItem[] items)
{
return new MenuItem(I18N.GetString(text), items);
}
private void LoadMenu()
{
this.contextMenu1 = new System.Windows.Forms.ContextMenu();
this.enableItem = new System.Windows.Forms.MenuItem();
this.modeItem = new System.Windows.Forms.MenuItem();
this.PACModeItem = new System.Windows.Forms.MenuItem();
this.globalModeItem = new System.Windows.Forms.MenuItem();
this.AutoStartupItem = new System.Windows.Forms.MenuItem();
this.ShareOverLANItem = new System.Windows.Forms.MenuItem();
this.ServersItem = new System.Windows.Forms.MenuItem();
this.SeperatorItem = new System.Windows.Forms.MenuItem();
this.ConfigItem = new System.Windows.Forms.MenuItem();
this.menuItem4 = new System.Windows.Forms.MenuItem();
this.editPACFileItem = new System.Windows.Forms.MenuItem();
this.QRCodeItem = new System.Windows.Forms.MenuItem();
this.ShowLogItem = new System.Windows.Forms.MenuItem();
this.aboutItem = new System.Windows.Forms.MenuItem();
this.menuItem3 = new System.Windows.Forms.MenuItem();
this.quitItem = new System.Windows.Forms.MenuItem();
this.menuItem1 = new System.Windows.Forms.MenuItem();
//
// contextMenu1
//
this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.enableItem,
this.modeItem,
this.ServersItem,
this.menuItem1,
this.AutoStartupItem,
this.ShareOverLANItem,
this.editPACFileItem,
this.menuItem4,
this.QRCodeItem,
this.ShowLogItem,
this.aboutItem,
this.menuItem3,
this.quitItem});
//
// enableItem
//
this.enableItem.Index = 0;
this.enableItem.Text = I18N.GetString("Enable");
this.enableItem.Click += new System.EventHandler(this.EnableItem_Click);
//
// modeMenu
//
this.modeItem.Index = 1;
this.modeItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.PACModeItem,
this.globalModeItem});
this.modeItem.Text = I18N.GetString("Mode");
//
// PACModeItem
//
this.PACModeItem.Index = 0;
this.PACModeItem.Text = I18N.GetString("PAC");
this.PACModeItem.Click += new System.EventHandler(this.PACModeItem_Click);
//
// globalModeItem
//
this.globalModeItem.Index = 1;
this.globalModeItem.Text = I18N.GetString("Global");
this.globalModeItem.Click += new System.EventHandler(this.GlobalModeItem_Click);
//
// ServersItem
//
this.ServersItem.Index = 2;
this.ServersItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.SeperatorItem,
this.ConfigItem});
this.ServersItem.Text = I18N.GetString("Servers");
//
// SeperatorItem
//
this.SeperatorItem.Index = 0;
this.SeperatorItem.Text = "-";
//
// ConfigItem
//
this.ConfigItem.Index = 1;
this.ConfigItem.Text = I18N.GetString("Edit Servers...");
this.ConfigItem.Click += new System.EventHandler(this.Config_Click);
//
// menuItem1
//
this.menuItem1.Index = 3;
this.menuItem1.Text = "-";
//
// AutoStartupItem
//
this.AutoStartupItem.Index = 4;
this.AutoStartupItem.Text = I18N.GetString("Start on Boot");
this.AutoStartupItem.Click += new System.EventHandler(this.AutoStartupItem_Click);
//
// ShareOverLANItem
//
this.ShareOverLANItem.Index = 5;
this.ShareOverLANItem.Text = I18N.GetString("Share over LAN");
this.ShareOverLANItem.Click += new System.EventHandler(this.ShareOverLANItem_Click);
//
// editPACFileItem
//
this.editPACFileItem.Index = 6;
this.editPACFileItem.Text = I18N.GetString("Edit PAC File...");
this.editPACFileItem.Click += new System.EventHandler(this.EditPACFileItem_Click);
//
// menuItem4
//
this.menuItem4.Index = 7;
this.menuItem4.Text = "-";
//
// QRCodeItem
//
this.QRCodeItem.Index = 8;
this.QRCodeItem.Text = I18N.GetString("Show QRCode...");
this.QRCodeItem.Click += new System.EventHandler(this.QRCodeItem_Click);
//
// ShowLogItem
//
this.ShowLogItem.Index = 9;
this.ShowLogItem.Text = I18N.GetString("Show Logs...");
this.ShowLogItem.Click += new System.EventHandler(this.ShowLogItem_Click);
//
// aboutItem
//
this.aboutItem.Index = 10;
this.aboutItem.Text = I18N.GetString("About...");
this.aboutItem.Click += new System.EventHandler(this.AboutItem_Click);
//
// menuItem3
//
this.menuItem3.Index = 11;
this.menuItem3.Text = "-";
//
// quitItem
//
this.quitItem.Index = 12;
this.quitItem.Text = I18N.GetString("Quit");
this.quitItem.Click += new System.EventHandler(this.Quit_Click);
this.contextMenu1 = new ContextMenu(new MenuItem[] {
this.enableItem = CreateMenuItem("Enable", new EventHandler(this.EnableItem_Click)),
CreateMenuGroup("Mode", new MenuItem[] {
this.PACModeItem = CreateMenuItem("PAC", new EventHandler(this.PACModeItem_Click)),
this.globalModeItem = CreateMenuItem("Global", new EventHandler(this.GlobalModeItem_Click))
}),
this.ServersItem = CreateMenuGroup("Servers", new MenuItem[] {
this.SeperatorItem = new MenuItem("-"),
this.ConfigItem = CreateMenuItem("Edit Servers...", new EventHandler(this.Config_Click))
}),
new MenuItem("-"),
this.AutoStartupItem = CreateMenuItem("Start on Boot", new EventHandler(this.AutoStartupItem_Click)),
this.ShareOverLANItem = CreateMenuItem("Share over LAN", new EventHandler(this.ShareOverLANItem_Click)),
CreateMenuItem("Edit PAC File...", new EventHandler(this.EditPACFileItem_Click)),
new MenuItem("-"),
CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)),
CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)),
CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)),
new MenuItem("-"),
CreateMenuItem("Quit", new EventHandler(this.Quit_Click))
});
}
private void controller_ConfigChanged(object sender, EventArgs e)
@@ -347,7 +231,7 @@ namespace Shadowsocks.View
{
if (configForm != null)
{
configForm.Focus();
configForm.Activate();
}
else
{
@@ -390,12 +274,15 @@ namespace Shadowsocks.View
private void AboutItem_Click(object sender, EventArgs e)
{
Process.Start("https://github.com/clowwindy/shadowsocks-csharp");
Process.Start("https://github.com/shadowsocks/shadowsocks-csharp");
}
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
private void notifyIcon1_DoubleClick(object sender, MouseEventArgs e)
{
ShowConfigForm();
if (e.Button == MouseButtons.Left)
{
ShowConfigForm();
}
}
private void EnableItem_Click(object sender, EventArgs e)


+ 8
- 36
shadowsocks-csharp/View/QRCodeForm.cs View File

@@ -1,4 +1,4 @@
using QRCode4CS;
using ZXing.QrCode.Internal;
using Shadowsocks.Controller;
using Shadowsocks.Properties;
using System;
@@ -28,48 +28,20 @@ namespace Shadowsocks.View
private void GenQR(string ssconfig)
{
string qrText = ssconfig;
QRCode4CS.Options options = new QRCode4CS.Options();
options.Text = qrText;
QRCode4CS.QRCode qrCoded = null;
bool success = false;
foreach (var level in new QRErrorCorrectLevel[]{QRErrorCorrectLevel.H, QRErrorCorrectLevel.Q, QRErrorCorrectLevel.M, QRErrorCorrectLevel.L})
{
for (int i = 3; i < 10; i++)
{
try
{
options.TypeNumber = i;
options.CorrectLevel = level;
qrCoded = new QRCode4CS.QRCode(options);
qrCoded.Make();
success = true;
break;
}
catch
{
qrCoded = null;
continue;
}
}
if (success)
break;
}
if (qrCoded == null)
{
return;
}
int blockSize = Math.Max(200 / qrCoded.GetModuleCount(), 1);
Bitmap drawArea = new Bitmap((qrCoded.GetModuleCount() * blockSize), (qrCoded.GetModuleCount() * blockSize));
QRCode code = ZXing.QrCode.Internal.Encoder.encode(qrText, ErrorCorrectionLevel.M);
ByteMatrix m = code.Matrix;
int blockSize = Math.Max(200 / m.Height, 1);
Bitmap drawArea = new Bitmap((m.Width * blockSize), (m.Height * blockSize));
using (Graphics g = Graphics.FromImage(drawArea))
{
g.Clear(Color.White);
using (Brush b = new SolidBrush(Color.Black))
{
for (int row = 0; row < qrCoded.GetModuleCount(); row++)
for (int row = 0; row < m.Width; row++)
{
for (int col = 0; col < qrCoded.GetModuleCount(); col++)
for (int col = 0; col < m.Height; col++)
{
if (qrCoded.IsDark(row, col))
if (m[row, col] != 0)
{
g.FillRectangle(b, blockSize * row, blockSize * col, blockSize, blockSize);
}


+ 23
- 19
shadowsocks-csharp/shadowsocks-csharp.csproj View File

@@ -57,6 +57,7 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
@@ -69,22 +70,34 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<Compile Include="3rd\QRCodeCS.cs" />
<Compile Include="3rd\SimpleJson.cs" />
<Compile Include="3rd\zxing\BitArray.cs" />
<Compile Include="3rd\zxing\BlockPair.cs" />
<Compile Include="3rd\zxing\ByteMatrix.cs" />
<Compile Include="3rd\zxing\Encoder.cs" />
<Compile Include="3rd\zxing\ErrorCorrectionLevel.cs" />
<Compile Include="3rd\zxing\GenericGF.cs" />
<Compile Include="3rd\zxing\GenericGFPoly.cs" />
<Compile Include="3rd\zxing\MaskUtil.cs" />
<Compile Include="3rd\zxing\MatrixUtil.cs" />
<Compile Include="3rd\zxing\Mode.cs" />
<Compile Include="3rd\zxing\QRCode.cs" />
<Compile Include="3rd\zxing\ReedSolomonEncoder.cs" />
<Compile Include="3rd\zxing\Version.cs" />
<Compile Include="Controller\AutoStartup.cs" />
<Compile Include="Controller\FileManager.cs" />
<Compile Include="Controller\I18N.cs" />
<Compile Include="Controller\Logging.cs" />
<Compile Include="Controller\UpdateChecker.cs" />
<Compile Include="Encrypt\EncryptorBase.cs" />
<Compile Include="Encrypt\EncryptorFactory.cs" />
<Compile Include="Encrypt\IVEncryptor.cs" />
<Compile Include="Encrypt\PolarSSL.cs" />
<Compile Include="Encrypt\PolarSSLEncryptor.cs" />
<Compile Include="Encrypt\Sodium.cs" />
<Compile Include="Encrypt\SodiumEncryptor.cs" />
<Compile Include="Encrypt\TableEncryptor.cs" />
<Compile Include="Encrypt\IEncryptor.cs" />
<Compile Include="Encryption\EncryptorBase.cs" />
<Compile Include="Encryption\EncryptorFactory.cs" />
<Compile Include="Encryption\IVEncryptor.cs" />
<Compile Include="Encryption\PolarSSL.cs" />
<Compile Include="Encryption\PolarSSLEncryptor.cs" />
<Compile Include="Encryption\Sodium.cs" />
<Compile Include="Encryption\SodiumEncryptor.cs" />
<Compile Include="Encryption\TableEncryptor.cs" />
<Compile Include="Encryption\IEncryptor.cs" />
<Compile Include="Controller\PACServer.cs" />
<Compile Include="Model\Server.cs" />
<Compile Include="Model\Configuration.cs" />
@@ -131,15 +144,6 @@
</None>
<None Include="Data\libsscrypto.dll.gz" />
<None Include="Data\polipo.exe.gz" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<None Include="Data\proxy.pac.txt.gz" />
</ItemGroup>
<ItemGroup>


+ 1
- 1
test/Properties/AssemblyInfo.cs View File

@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("test")]
[assembly: AssemblyCopyright("Copyright © 2014")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]


+ 1
- 1
test/UnitTest.cs View File

@@ -1,7 +1,7 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shadowsocks.Controller;
using Shadowsocks.Encrypt;
using Shadowsocks.Encryption;
using System.Threading;
using System.Collections.Generic;


Loading…
Cancel
Save