From 1b126fa78e85b31d24f7d7cffbff125fcddd74b1 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 24 Dec 2014 08:08:55 +0800 Subject: [PATCH 01/32] use zxing instead --- shadowsocks-csharp/3rd/QRCodeCS.cs | 1209 -------------------- shadowsocks-csharp/3rd/zxing/BitArray.cs | 488 ++++++++ shadowsocks-csharp/3rd/zxing/BitMatrix.cs | 435 +++++++ shadowsocks-csharp/3rd/zxing/BlockPair.cs | 40 + shadowsocks-csharp/3rd/zxing/ByteMatrix.cs | 148 +++ shadowsocks-csharp/3rd/zxing/EncodeHintType.cs | 131 +++ shadowsocks-csharp/3rd/zxing/Encoder.cs | 762 ++++++++++++ .../3rd/zxing/ErrorCorrectionLevel.cs | 109 ++ shadowsocks-csharp/3rd/zxing/FormatInformation.cs | 197 ++++ shadowsocks-csharp/3rd/zxing/GenericGF.cs | 210 ++++ shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs | 331 ++++++ shadowsocks-csharp/3rd/zxing/MaskUtil.cs | 271 +++++ shadowsocks-csharp/3rd/zxing/MatrixUtil.cs | 604 ++++++++++ shadowsocks-csharp/3rd/zxing/Mode.cs | 179 +++ shadowsocks-csharp/3rd/zxing/QRCode.cs | 125 ++ shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs | 84 ++ shadowsocks-csharp/3rd/zxing/Version.cs | 685 +++++++++++ shadowsocks-csharp/View/QRCodeForm.cs | 44 +- shadowsocks-csharp/shadowsocks-csharp.csproj | 17 +- 19 files changed, 4823 insertions(+), 1246 deletions(-) delete mode 100644 shadowsocks-csharp/3rd/QRCodeCS.cs create mode 100755 shadowsocks-csharp/3rd/zxing/BitArray.cs create mode 100755 shadowsocks-csharp/3rd/zxing/BitMatrix.cs create mode 100755 shadowsocks-csharp/3rd/zxing/BlockPair.cs create mode 100755 shadowsocks-csharp/3rd/zxing/ByteMatrix.cs create mode 100755 shadowsocks-csharp/3rd/zxing/EncodeHintType.cs create mode 100755 shadowsocks-csharp/3rd/zxing/Encoder.cs create mode 100755 shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs create mode 100755 shadowsocks-csharp/3rd/zxing/FormatInformation.cs create mode 100755 shadowsocks-csharp/3rd/zxing/GenericGF.cs create mode 100755 shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs create mode 100755 shadowsocks-csharp/3rd/zxing/MaskUtil.cs create mode 100755 shadowsocks-csharp/3rd/zxing/MatrixUtil.cs create mode 100755 shadowsocks-csharp/3rd/zxing/Mode.cs create mode 100755 shadowsocks-csharp/3rd/zxing/QRCode.cs create mode 100755 shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs create mode 100755 shadowsocks-csharp/3rd/zxing/Version.cs diff --git a/shadowsocks-csharp/3rd/QRCodeCS.cs b/shadowsocks-csharp/3rd/QRCodeCS.cs deleted file mode 100644 index a380c978..00000000 --- a/shadowsocks-csharp/3rd/QRCodeCS.cs +++ /dev/null @@ -1,1209 +0,0 @@ -//--------------------------------------------------------------------- -// QRCode for C#4.0 Silverlight is translation of QRCode for JavaScript -// https://github.com/jeromeetienne/jquery-qrcode/ -// -// Copyright (c) 2009 Kazuhiko Arase -// -// URL: http://www.d-project.com/ -// -// Licensed under the MIT license: -// http://www.opensource.org/licenses/mit-license.php -// -// The word "QR Code" is registered trademark of -// DENSO WAVE INCORPORATED -// http://www.denso-wave.com/qrcode/faqpatent-e.html -// -//--------------------------------------------------------------------- -namespace QRCode4CS -{ - using System; - using System.Collections.Generic; - - - public class Error : Exception - { - public Error() { } - public Error(string message) : base(message) { } - public Error(string message, Exception inner) : base(message, inner) { } - } - - public enum QRMode : int - { - MODE_NUMBER = 1 << 0, - MODE_ALPHA_NUM = 1 << 1, - MODE_8BIT_BYTE = 1 << 2, - MODE_KANJI = 1 << 3 - } - - public enum QRErrorCorrectLevel : int - { - L = 1, - M = 0, - Q = 3, - H = 2 - } - - public enum QRMaskPattern : int - { - PATTERN000 = 0, - PATTERN001 = 1, - PATTERN010 = 2, - PATTERN011 = 3, - PATTERN100 = 4, - PATTERN101 = 5, - PATTERN110 = 6, - PATTERN111 = 7 - } - - public struct Options - { - public int Width { get; set; } - public int Height { get; set; } - public QRErrorCorrectLevel CorrectLevel { get; set; } - public int TypeNumber { get; set; } - public string Text { get; set; } - - public Options(string text) - : this() - { - Width = 256; - Height = 256; - TypeNumber = 4; - CorrectLevel = QRErrorCorrectLevel.H; - Text = text; - } - } - - internal static class QRUtil - { - internal const int G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0); - internal const int G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0); - internal const int G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1); - internal static readonly int[][] PATTERN_POSITION_TABLE = new int[][] { - new int[] {}, - new int [] {6, 18}, - new int [] {6, 22}, - new int [] {6, 26}, - new int [] {6, 30}, - new int [] {6, 34}, - new int [] {6, 22, 38}, - new int [] {6, 24, 42}, - new int [] {6, 26, 46}, - new int [] {6, 28, 50}, - new int [] {6, 30, 54}, - new int [] {6, 32, 58}, - new int [] {6, 34, 62}, - new int [] {6, 26, 46, 66}, - new int [] {6, 26, 48, 70}, - new int [] {6, 26, 50, 74}, - new int [] {6, 30, 54, 78}, - new int [] {6, 30, 56, 82}, - new int [] {6, 30, 58, 86}, - new int [] {6, 34, 62, 90}, - new int [] {6, 28, 50, 72, 94}, - new int [] {6, 26, 50, 74, 98}, - new int [] {6, 30, 54, 78, 102}, - new int [] {6, 28, 54, 80, 106}, - new int [] {6, 32, 58, 84, 110}, - new int [] {6, 30, 58, 86, 114}, - new int [] {6, 34, 62, 90, 118}, - new int [] {6, 26, 50, 74, 98, 122}, - new int [] {6, 30, 54, 78, 102, 126}, - new int [] {6, 26, 52, 78, 104, 130}, - new int [] {6, 30, 56, 82, 108, 134}, - new int [] {6, 34, 60, 86, 112, 138}, - - new int [] {6, 30, 58, 86, 114, 142}, - new int [] {6, 34, 62, 90, 118, 146}, - 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} - }; - internal static int GetLengthInBits(QRMode mode, int type) - { - - if (1 <= type && type < 10) - { - - // 1 - 9 - - switch (mode) - { - case QRMode.MODE_NUMBER: return 10; - case QRMode.MODE_ALPHA_NUM: return 9; - case QRMode.MODE_8BIT_BYTE: return 8; - case QRMode.MODE_KANJI: return 8; - default: - throw new Error("mode:" + mode); - } - - } - else if (type < 27) - { - - // 10 - 26 - - switch (mode) - { - case QRMode.MODE_NUMBER: return 12; - case QRMode.MODE_ALPHA_NUM: return 11; - case QRMode.MODE_8BIT_BYTE: return 16; - case QRMode.MODE_KANJI: return 10; - default: - throw new Error("mode:" + mode); - } - - } - else if (type < 41) - { - - // 27 - 40 - - switch (mode) - { - case QRMode.MODE_NUMBER: return 14; - case QRMode.MODE_ALPHA_NUM: return 13; - case QRMode.MODE_8BIT_BYTE: return 16; - case QRMode.MODE_KANJI: return 12; - default: - throw new Error("mode:" + mode); - } - - } - else - { - throw new Error("type:" + type); - } - } - - internal static double GetLostPoint(QRCode qrCode) - { - int moduleCount = qrCode.GetModuleCount(); - double lostPoint = 0; - for (int row = 0; row < moduleCount; row++) - { - - for (int col = 0; col < moduleCount; col++) - { - - var sameCount = 0; - var dark = qrCode.IsDark(row, col); - - for (var r = -1; r <= 1; r++) - { - - if (row + r < 0 || moduleCount <= row + r) - { - continue; - } - - for (var c = -1; c <= 1; c++) - { - - if (col + c < 0 || moduleCount <= col + c) - { - continue; - } - - if (r == 0 && c == 0) - { - continue; - } - - if (dark == qrCode.IsDark((int)((int)row + r), (int)((int)col + c))) - { - sameCount++; - } - } - } - - if (sameCount > 5) - { - lostPoint += (int)(3 + sameCount - 5); - } - } - } - - // LEVEL2 - - for (int row = 0; row < moduleCount - 1; row++) - { - for (int col = 0; col < moduleCount - 1; col++) - { - var count = 0; - if (qrCode.IsDark(row, col)) count++; - if (qrCode.IsDark(row + 1, col)) count++; - if (qrCode.IsDark(row, col + 1)) count++; - if (qrCode.IsDark(row + 1, col + 1)) count++; - if (count == 0 || count == 4) - { - lostPoint += 3; - } - } - } - - // LEVEL3 - - for (int row = 0; row < moduleCount; row++) - { - for (int col = 0; col < moduleCount - 6; col++) - { - if (qrCode.IsDark(row, col) - && !qrCode.IsDark(row, col + 1) - && qrCode.IsDark(row, col + 2) - && qrCode.IsDark(row, col + 3) - && qrCode.IsDark(row, col + 4) - && !qrCode.IsDark(row, col + 5) - && qrCode.IsDark(row, col + 6)) - { - lostPoint += 40; - } - } - } - - for (int col = 0; col < moduleCount; col++) - { - for (int row = 0; row < moduleCount - 6; row++) - { - if (qrCode.IsDark(row, col) - && !qrCode.IsDark(row + 1, col) - && qrCode.IsDark(row + 2, col) - && qrCode.IsDark(row + 3, col) - && qrCode.IsDark(row + 4, col) - && !qrCode.IsDark(row + 5, col) - && qrCode.IsDark(row + 6, col)) - { - lostPoint += 40; - } - } - } - - // LEVEL4 - - int darkCount = 0; - - for (int col = 0; col < moduleCount; col++) - { - for (int row = 0; row < moduleCount; row++) - { - if (qrCode.IsDark(row, col)) - { - darkCount++; - } - } - } - - double ratio = Math.Abs(100.0 * darkCount / moduleCount / moduleCount - 50) / 5; - lostPoint += ratio * 10; - - return lostPoint; - - } - - - - - internal static int GetBCHTypeInfo(int data) - { - int d = (data << 10); - int s = 0; - while ((s = (int)(QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G15))) >= 0) - { - d ^= (Convert.ToInt32(QRUtil.G15) << s); - } - return (int)((data << 10) | d) ^ QRUtil.G15_MASK; - } - - internal static int GetBCHTypeNumber(int data) - { - int d = data << 12; - while (QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G18) >= 0) - { - d ^= (QRUtil.G18 << (QRUtil.GetBCHDigit(d) - QRUtil.GetBCHDigit(QRUtil.G18))); - } - return (data << 12) | d; - } - - internal static int GetBCHDigit(int dataInt) - { - - int digit = 0; - uint data = Convert.ToUInt32(dataInt); - while (data != 0) - { - digit++; - data >>= 1; - } - - return digit; - } - - internal static int[] GetPatternPosition(int typeNumber) - { - return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; - } - - internal static bool GetMask(QRMaskPattern maskPattern, int i, int j) - { - - switch (maskPattern) - { - - case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; - case QRMaskPattern.PATTERN001: return i % 2 == 0; - case QRMaskPattern.PATTERN010: return j % 3 == 0; - case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; - case QRMaskPattern.PATTERN100: return (Math.Floor((double) (i / 2)) + Math.Floor((double) (j / 3))) % 2 == 0; - case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; - case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; - case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; - - default: - throw new Error("bad maskPattern:" + maskPattern); - } - } - - - - internal static QRPolynomial GetErrorCorrectPolynomial(int errorCorrectLength) - { - QRPolynomial a = new QRPolynomial(new DataCache() { 1 }, 0); - - for (int i = 0; i < errorCorrectLength; i++) - { - a = a.Multiply(new QRPolynomial(new DataCache() { 1, QRMath.GExp(i) }, 0)); - } - - return a; - } - } - - internal struct QRPolynomial - { - private int[] m_num; - public QRPolynomial(DataCache num, int shift) - : this() - { - if (num == null) - { - throw new Error(); - } - - int offset = 0; - - while (offset < num.Count && num[offset] == 0) - { - offset++; - } - - this.m_num = new int[num.Count - offset + shift]; - for (int i = 0; i < num.Count - offset; i++) - { - this.m_num[i] = num[(int)(i + offset)]; - } - } - - public int Get(int index) - { - return this.m_num[(int)index]; - } - - public int GetLength() - { - return (int)this.m_num.Length; - } - - public QRPolynomial Multiply(QRPolynomial e) - { - - var num = new DataCache(this.GetLength() + e.GetLength() - 1); - - for (int i = 0; i < this.GetLength(); i++) - { - for (int j = 0; j < e.GetLength(); j++) - { - num[i + j] ^= QRMath.GExp(QRMath.GLog(this.Get(i)) + QRMath.GLog(e.Get(j))); - } - } - - return new QRPolynomial(num, 0); - } - - public QRPolynomial Mod(QRPolynomial e) - { - - if (Convert.ToInt64(this.GetLength()) - Convert.ToInt64(e.GetLength()) < 0) - { - return this; - } - - int ratio = QRMath.GLog(this.Get(0)) - QRMath.GLog(e.Get(0)); - - var num = new DataCache(this.GetLength()); - - for (int i = 0; i < this.GetLength(); i++) - { - num[i] = this.Get(i); - } - - for (int i = 0; i < e.GetLength(); i++) - { - num[i] ^= QRMath.GExp(QRMath.GLog(e.Get(i)) + ratio); - } - - // recursive call - return new QRPolynomial(num, 0).Mod(e); - } - } - - - internal static class QRMath - { - private static readonly int[] EXP_TABLE; - private static readonly int[] LOG_TABLE; - - static QRMath() - { - EXP_TABLE = new int[256]; - LOG_TABLE = new int[256]; - for (int i = 0; i < 8; i++) - { - QRMath.EXP_TABLE[i] = (int)(1 << (int)i); - } - for (int i = 8; i < 256; i++) - { - QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] - ^ QRMath.EXP_TABLE[i - 5] - ^ QRMath.EXP_TABLE[i - 6] - ^ QRMath.EXP_TABLE[i - 8]; - } - for (int i = 0; i < 255; i++) - { - QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i; - } - } - - internal static int GLog(int n) - { - if (n < 1) - { - throw new Error("glog(" + n + ")"); - } - return QRMath.LOG_TABLE[n]; - } - - internal static int GExp(int n) - { - while (n < 0) - { - n += 255; - } - while (n >= 256) - { - n -= 255; - } - return QRMath.EXP_TABLE[n]; - } - } - - public struct QR8bitByte - { - public QRMode Mode { get; private set; } - private string m_data { get; set; } - - public QR8bitByte(string data) - : this() - { - m_data = data; - Mode = QRMode.MODE_8BIT_BYTE; - } - - public int Length - { - get - { - return m_data.Length; - } - } - - public void Write(QRBitBuffer buffer) - { - for (int i = 0; i < m_data.Length; ++i) - { - //item - buffer.Put(m_data[i], 8); - } - ///buffer = Data; - } - - - } - - internal class DataCache : List - { - public DataCache(int capacity) - : base() - { - for (int i = 0; i < capacity; i++) - { - base.Add(0); - } - } - - public DataCache() - : base() - { - - } - - - } - - internal struct QRRSBlock - { - private static readonly int[][] RS_BLOCK_TABLE = new int[][] { - // L - // M - // Q - // H - - // 1 - new int [] {1, 26, 19}, - new int [] {1, 26, 16}, - new int [] {1, 26, 13}, - new int [] {1, 26, 9}, - - // 2 - new int [] {1, 44, 34}, - new int [] {1, 44, 28}, - new int [] {1, 44, 22}, - new int [] {1, 44, 16}, - - // 3 - new int [] {1, 70, 55}, - new int [] {1, 70, 44}, - new int [] {2, 35, 17}, - new int [] {2, 35, 13}, - - // 4 - new int [] {1, 100, 80}, - new int [] {2, 50, 32}, - new int [] {2, 50, 24}, - new int [] {4, 25, 9}, - - // 5 - new int [] {1, 134, 108}, - new int [] {2, 67, 43}, - new int [] {2, 33, 15, 2, 34, 16}, - new int [] {2, 33, 11, 2, 34, 12}, - - // 6 - new int [] {2, 86, 68}, - new int [] {4, 43, 27}, - new int [] {4, 43, 19}, - new int [] {4, 43, 15}, - - // 7 - new int [] {2, 98, 78}, - new int [] {4, 49, 31}, - new int [] {2, 32, 14, 4, 33, 15}, - new int [] {4, 39, 13, 1, 40, 14}, - - // 8 - new int [] {2, 121, 97}, - new int [] {2, 60, 38, 2, 61, 39}, - new int [] {4, 40, 18, 2, 41, 19}, - new int [] {4, 40, 14, 2, 41, 15}, - - // 9 - new int [] {2, 146, 116}, - new int [] {3, 58, 36, 2, 59, 37}, - new int [] {4, 36, 16, 4, 37, 17}, - new int [] {4, 36, 12, 4, 37, 13}, - - // 10 - new int [] {2, 86, 68, 2, 87, 69}, - new int [] {4, 69, 43, 1, 70, 44}, - new int [] {6, 43, 19, 2, 44, 20}, - new int [] {6, 43, 15, 2, 44, 16} - }; - - - public int DataCount { get; private set; } - public int TotalCount { get; set; } - - public QRRSBlock(int totalCount, int dataCount) - : this() - { - TotalCount = totalCount; - DataCount = dataCount; - } - public static List GetRSBlocks(int typeNumber, QRErrorCorrectLevel errorCorrectLevel) - { - - int[] rsBlock = GetRsBlockTable(typeNumber, errorCorrectLevel); - - if (rsBlock == null) - { - throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); - } - - int length = (int)rsBlock.Length / 3; - - var list = new List(); - - for (int i = 0; i < length; i++) - { - - int count = rsBlock[i * 3 + 0]; - int totalCount = rsBlock[i * 3 + 1]; - int dataCount = rsBlock[i * 3 + 2]; - - for (int j = 0; j < count; j++) - { - list.Add(new QRRSBlock(totalCount, dataCount)); - } - } - - return list; - } - - private static int[] GetRsBlockTable(int typeNumber, QRErrorCorrectLevel errorCorrectLevel) - { - switch (errorCorrectLevel) - { - case QRErrorCorrectLevel.L: - return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; - case QRErrorCorrectLevel.M: - return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; - case QRErrorCorrectLevel.Q: - return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; - case QRErrorCorrectLevel.H: - return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; - default: - return null; - } - } - } - - public class QRCode - { - private const int PAD0 = 0xEC; - private const int PAD1 = 0x11; - private List m_dataList = new List(); - private int m_typeNumber; - private DataCache m_dataCache; - private int m_moduleCount; - private bool?[][] m_modules; - private QRErrorCorrectLevel m_errorCorrectLevel; - public QRCode(Options options) - : this(options.TypeNumber, options.CorrectLevel) - { - AddData(options.Text); - } - - public QRCode(int typeNumber, QRErrorCorrectLevel level) - { - m_typeNumber = typeNumber; - m_errorCorrectLevel = level; - m_dataCache = null; - } - - public void AddData(string data) - { - m_dataCache = null; - m_dataList.Add(new QR8bitByte(data)); - } - - public void Make() - { - MakeImpl(false, GetBestMaskPattern()); - } - - private QRMaskPattern GetBestMaskPattern() - { - double minLostPoint = 0; - QRMaskPattern pattern = 0; - for (int i = 0; i < 8; i++) - { - this.MakeImpl(true, (QRMaskPattern)i); - - double lostPoint = QRUtil.GetLostPoint(this); - - if (i == 0 || minLostPoint > lostPoint) - { - minLostPoint = lostPoint; - pattern = (QRMaskPattern)i; - } - } - - return pattern; - } - - - - private void MakeImpl(bool test, QRMaskPattern maskPattern) - { - m_moduleCount = this.m_typeNumber * 4 + 17; - m_modules = new bool?[m_moduleCount][]; - for (int row = 0; row < m_moduleCount; row++) - { - - m_modules[row] = new bool?[(m_moduleCount)]; - - for (var col = 0; col < m_moduleCount; col++) - { - m_modules[row][col] = null; //(col + row) % 3; - } - } - - this.SetupPositionProbePattern(0, 0); - this.SetupPositionProbePattern(m_moduleCount - 7, 0); - this.SetupPositionProbePattern(0, m_moduleCount - 7); - this.SetupPositionAdjustPattern(); - this.SetupTimingPattern(); - this.setupTypeInfo(test, maskPattern); - - if (m_typeNumber >= 7) - { - this.setupTypeNumber(test); - } - - if (this.m_dataCache == null) - { - this.m_dataCache = CreateData(this.m_typeNumber, this.m_errorCorrectLevel, this.m_dataList); - } - - MapData(this.m_dataCache, maskPattern); - - } - - public bool IsDark(int row, int col) - { - return m_modules[(int)row][(int)col].Value; - } - - private void SetupTimingPattern() - { - for (var r = 8; r < this.m_moduleCount - 8; r++) - { - if (this.m_modules[r][6] != null) - { - continue; - } - this.m_modules[r][6] = (r % 2 == 0); - } - - for (var c = 8; c < this.m_moduleCount - 8; c++) - { - if (this.m_modules[6][c] != null) - { - continue; - } - this.m_modules[6][c] = (c % 2 == 0); - } - } - - private void setupTypeNumber(bool test) - { - var bits = QRUtil.GetBCHTypeNumber(m_typeNumber); - - for (var i = 0; i < 18; i++) - { - var mod = (!test && ((bits >> i) & 1) == 1); - this.m_modules[(int)Math.Floor((double) (i / 3))][i % 3 + this.m_moduleCount - 8 - 3] = mod; - } - - for (var i = 0; i < 18; i++) - { - var mod = (!test && ((bits >> i) & 1) == 1); - this.m_modules[i % 3 + this.m_moduleCount - 8 - 3][(int)Math.Floor((double) (i / 3))] = mod; - } - } - private void SetupPositionAdjustPattern() - { - var pos = QRUtil.GetPatternPosition(m_typeNumber); - - for (var i = 0; i < pos.Length; i++) - { - - for (var j = 0; j < pos.Length; j++) - { - - var row = pos[i]; - var col = pos[j]; - - if (this.m_modules[row][col] != null) - { - continue; - } - - for (var r = -2; r <= 2; r++) - { - - for (var c = -2; c <= 2; c++) - { - - if (r == -2 || r == 2 || c == -2 || c == 2 - || (r == 0 && c == 0)) - { - this.m_modules[row + r][col + c] = true; - } - else - { - this.m_modules[row + r][col + c] = false; - } - } - } - } - } - } - - - private void setupTypeInfo(bool test, QRMaskPattern maskPattern) - { - - var data = ((int)this.m_errorCorrectLevel << 3) | (int)maskPattern; - var bits = QRUtil.GetBCHTypeInfo(data); - - // vertical - for (var i = 0; i < 15; i++) - { - - var mod = (!test && ((bits >> i) & 1) == 1); - - if (i < 6) - { - this.m_modules[i][8] = mod; - } - else if (i < 8) - { - this.m_modules[i + 1][8] = mod; - } - else - { - this.m_modules[this.m_moduleCount - 15 + i][8] = mod; - } - } - - // horizontal - for (var i = 0; i < 15; i++) - { - - var mod = (!test && ((bits >> i) & 1) == 1); - - if (i < 8) - { - this.m_modules[8][this.m_moduleCount - i - 1] = mod; - } - else if (i < 9) - { - this.m_modules[8][15 - i - 1 + 1] = mod; - } - else - { - this.m_modules[8][15 - i - 1] = mod; - } - } - - // fixed module - this.m_modules[this.m_moduleCount - 8][8] = (!test); - - } - - private void MapData(DataCache data, QRMaskPattern maskPattern) - { - - int inc = -1; - int row = (int)this.m_moduleCount - 1; - int bitIndex = 7; - int byteIndex = 0; - - for (var col = this.m_moduleCount - 1; col > 0; col -= 2) - { - - if (col == 6) col--; - - while (true) - { - - for (int c = 0; c < 2; c++) - { - - if (this.m_modules[row][col - c] == null) - { - - bool dark = false; - - if (byteIndex < data.Count) - { - dark = (((Convert.ToUInt32(data[byteIndex]) >> bitIndex) & 1) == 1); - } - - bool mask = QRUtil.GetMask(maskPattern, (int)row, col - c); - - if (mask) - { - dark = !dark; - } - - this.m_modules[row][col - c] = dark; - bitIndex--; - - if (bitIndex == -1) - { - byteIndex++; - bitIndex = 7; - } - } - } - - row += inc; - - if (row < 0 || this.m_moduleCount <= row) - { - row -= inc; - inc = -inc; - break; - } - } - } - - } - - private DataCache CreateData(int typeNumber, QRErrorCorrectLevel errorCorrectLevel, List dataList) - { - List rsBlocks = QRRSBlock.GetRSBlocks(typeNumber, errorCorrectLevel); - - var buffer = new QRBitBuffer(); - - for (int i = 0; i < dataList.Count; i++) - { - QR8bitByte data = dataList[i]; - - buffer.Put((int)data.Mode, 4); - buffer.Put(data.Length, QRUtil.GetLengthInBits(data.Mode, typeNumber)); - data.Write(buffer); - } - - // calc num max data. - int totalDataCount = 0; - for (var i = 0; i < rsBlocks.Count; i++) - { - totalDataCount += rsBlocks[i].DataCount; - } - - if (buffer.GetLengthInBits() > totalDataCount * 8) - { - throw new Error("code length overflow. (" - + buffer.GetLengthInBits() - + ">" - + totalDataCount * 8 - + ")"); - } - - // end code - if (buffer.GetLengthInBits() + 4 <= totalDataCount * 8) - { - buffer.Put(0, 4); - } - - // padding - while (buffer.GetLengthInBits() % 8 != 0) - { - buffer.PutBit(false); - } - - // padding - while (true) - { - - if (buffer.GetLengthInBits() >= totalDataCount * 8) - { - break; - } - buffer.Put(QRCode.PAD0, 8); - - if (buffer.GetLengthInBits() >= totalDataCount * 8) - { - break; - } - buffer.Put(QRCode.PAD1, 8); - } - - return CreateBytes(buffer, rsBlocks); - } - - private DataCache CreateBytes(QRBitBuffer buffer, List rsBlocks) - { - - int offset = 0; - - int maxDcCount = 0; - int maxEcCount = 0; - - var dcdata = new DataCache[(rsBlocks.Count)]; - var ecdata = new DataCache[(rsBlocks.Count)]; - - for (int r = 0; r < rsBlocks.Count; r++) - { - - int dcCount = rsBlocks[(int)r].DataCount; - int ecCount = rsBlocks[(int)r].TotalCount - dcCount; - - maxDcCount = Math.Max(maxDcCount, dcCount); - maxEcCount = Math.Max(maxEcCount, ecCount); - - dcdata[r] = new DataCache(dcCount); - - for (int i = 0; i < dcdata[r].Count; i++) - { - dcdata[r][i] = 0xff & buffer.m_buffer[(int)(i + offset)]; - } - offset += dcCount; - - QRPolynomial rsPoly = QRUtil.GetErrorCorrectPolynomial(ecCount); - QRPolynomial rawPoly = new QRPolynomial(dcdata[r], rsPoly.GetLength() - 1); - - var modPoly = rawPoly.Mod(rsPoly); - ecdata[r] = new DataCache(rsPoly.GetLength() - 1); - for (int i = 0; i < ecdata[r].Count; i++) - { - int modIndex = i + modPoly.GetLength() - (int)ecdata[r].Count; - ecdata[r][i] = (modIndex >= 0) ? modPoly.Get(modIndex) : 0; - } - - } - - int totalCodeCount = 0; - for (int i = 0; i < rsBlocks.Count; i++) - { - totalCodeCount += rsBlocks[(int)i].TotalCount; - } - - var data = new DataCache(totalCodeCount); - int index = 0; - - for (int i = 0; i < maxDcCount; i++) - { - for (int r = 0; r < rsBlocks.Count; r++) - { - if (i < dcdata[r].Count) - { - data[index++] = dcdata[r][i]; - } - } - } - - for (int i = 0; i < maxEcCount; i++) - { - for (int r = 0; r < rsBlocks.Count; r++) - { - if (i < ecdata[r].Count) - { - data[index++] = ecdata[r][i]; - } - } - } - - return data; - - } - private void SetupPositionProbePattern(int row, int col) - { - for (int r = -1; r <= 7; r++) - { - - if (row + r <= -1 || this.m_moduleCount <= row + r) continue; - - for (int c = -1; c <= 7; c++) - { - - if (col + c <= -1 || this.m_moduleCount <= col + c) continue; - - if ((0 <= r && r <= 6 && (c == 0 || c == 6)) - || (0 <= c && c <= 6 && (r == 0 || r == 6)) - || (2 <= r && r <= 4 && 2 <= c && c <= 4)) - { - this.m_modules[row + r][col + c] = true; - } - else - { - this.m_modules[row + r][col + c] = false; - } - } - } - } - - public int GetModuleCount() - { - return this.m_moduleCount; - } - - internal int getBestMaskPattern() - { - - double minLostPoint = 0; - int pattern = 0; - - for (int i = 0; i < 8; i++) - { - - this.MakeImpl(true, (QRMaskPattern)i); - - double lostPoint = QRUtil.GetLostPoint(this); - - if (i == 0 || minLostPoint > lostPoint) - { - minLostPoint = lostPoint; - pattern = i; - } - } - - return pattern; - } - } - - public class QRBitBuffer - { - internal List m_buffer = new List(); - private int m_length = 0; - public bool Get(int index) - { - int bufIndex = Convert.ToInt32(Math.Floor((double) (index / 8))); - return ((Convert.ToUInt32(this.m_buffer[bufIndex]) >> (7 - index % 8)) & 1) == 1; - } - - public void Put(int num, int length) - { - for (var i = 0; i < length; i++) - { - this.PutBit(((Convert.ToUInt32(num) >> (length - i - 1)) & 1) == 1); - } - } - - public int GetLengthInBits() - { - return m_length; - } - - public void PutBit(bool bit) - { - - int bufIndex = (int)Math.Floor((double) (this.m_length / 8)); - if (this.m_buffer.Count <= bufIndex) - { - this.m_buffer.Add(0); - } - - if (bit) - { - this.m_buffer[bufIndex] |= (int)(Convert.ToUInt32(0x80) >> (this.m_length % 8)); - } - this.m_length++; - } - } -} diff --git a/shadowsocks-csharp/3rd/zxing/BitArray.cs b/shadowsocks-csharp/3rd/zxing/BitArray.cs new file mode 100755 index 00000000..e0234e1a --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/BitArray.cs @@ -0,0 +1,488 @@ +/* +* 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 +{ + /// + /// A simple, fast array of bits, represented compactly by an array of ints internally. + /// + /// Sean Owen + 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; + } + set + { + if (value) + bits[i >> 5] |= 1 << (i & 0x1F); + } + } + + public BitArray() + { + this.size = 0; + this.bits = new int[1]; + } + + public BitArray(int size) + { + if (size < 1) + { + throw new ArgumentException("size must be at least 1"); + } + this.size = size; + this.bits = makeArray(size); + } + + // For testing only + private BitArray(int[] bits, int size) + { + this.bits = bits; + this.size = size; + } + + 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; + } + } + + /// Flips bit i. + /// + /// + /// bit to set + /// + public void flip(int i) + { + bits[i >> 5] ^= 1 << (i & 0x1F); + } + + private static int numberOfTrailingZeros(int num) + { + var index = (-num & num)%37; + if (index < 0) + index *= -1; + return _lookup[index]; + } + + private static readonly int[] _lookup = + { + 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, + 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 + }; + + /// + /// Gets the next set. + /// + /// first bit to check + /// index of first bit that is set, starting from the given index, or size if none are set + /// at or beyond this given index + public int getNextSet(int from) + { + if (from >= size) + { + return size; + } + int bitsOffset = from >> 5; + int currentBits = bits[bitsOffset]; + // mask off lesser bits first + currentBits &= ~((1 << (from & 0x1F)) - 1); + while (currentBits == 0) + { + if (++bitsOffset == bits.Length) + { + return size; + } + currentBits = bits[bitsOffset]; + } + int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); + return result > size ? size : result; + } + + /// + /// see getNextSet(int) + /// + /// index to start looking for unset bit + /// index of next unset bit, or if none are unset until the end + public int getNextUnset(int from) + { + if (from >= size) + { + return size; + } + int bitsOffset = from >> 5; + int currentBits = ~bits[bitsOffset]; + // mask off lesser bits first + currentBits &= ~((1 << (from & 0x1F)) - 1); + while (currentBits == 0) + { + if (++bitsOffset == bits.Length) + { + return size; + } + currentBits = ~bits[bitsOffset]; + } + int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); + return result > size ? size : result; + } + + /// Sets a block of 32 bits, starting at bit i. + /// + /// + /// first bit to set + /// + /// the new value of the next 32 bits. Note again that the least-significant bit + /// corresponds to bit i, the next-least-significant to i+1, and so on. + /// + public void setBulk(int i, int newBits) + { + bits[i >> 5] = newBits; + } + + /// + /// Sets a range of bits. + /// + /// start of range, inclusive. + /// end of range, exclusive + public void setRange(int start, int end) + { + if (end < start) + { + throw new ArgumentException(); + } + if (end == start) + { + return; + } + end--; // will be easier to treat this as the last actually set bit -- inclusive + int firstInt = start >> 5; + int lastInt = end >> 5; + for (int i = firstInt; i <= lastInt; i++) + { + int firstBit = i > firstInt ? 0 : start & 0x1F; + int lastBit = i < lastInt ? 31 : end & 0x1F; + int mask; + if (firstBit == 0 && lastBit == 31) + { + mask = -1; + } + else + { + mask = 0; + for (int j = firstBit; j <= lastBit; j++) + { + mask |= 1 << j; + } + } + bits[i] |= mask; + } + } + + /// Clears all bits (sets to false). + public void clear() + { + int max = bits.Length; + for (int i = 0; i < max; i++) + { + bits[i] = 0; + } + } + + /// Efficient method to check if a range of bits is set, or not set. + /// + /// + /// start of range, inclusive. + /// + /// end of range, exclusive + /// + /// if true, checks that bits in range are set, otherwise checks that they are not set + /// + /// true iff all bits are set or not set in range, according to value argument + /// + /// IllegalArgumentException if end is less than or equal to start + public bool isRange(int start, int end, bool value) + { + if (end < start) + { + throw new System.ArgumentException(); + } + if (end == start) + { + return true; // empty range matches + } + end--; // will be easier to treat this as the last actually set bit -- inclusive + int firstInt = start >> 5; + int lastInt = end >> 5; + for (int i = firstInt; i <= lastInt; i++) + { + int firstBit = i > firstInt ? 0 : start & 0x1F; + int lastBit = i < lastInt ? 31 : end & 0x1F; + int mask; + if (firstBit == 0 && lastBit == 31) + { + mask = -1; + } + else + { + mask = 0; + for (int j = firstBit; j <= lastBit; j++) + { + mask |= 1 << j; + } + } + + // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is, + // equals the mask, or we're looking for 0s and the masked portion is not all 0s + if ((bits[i] & mask) != (value ? mask : 0)) + { + return false; + } + } + return true; + } + + /// + /// Appends the bit. + /// + /// The bit. + public void appendBit(bool bit) + { + ensureCapacity(size + 1); + if (bit) + { + bits[size >> 5] |= 1 << (size & 0x1F); + } + size++; + } + + /// underlying array of ints. The first element holds the first 32 bits, and the least + /// significant bit is bit 0. + /// + public int[] Array + { + get { return bits; } + } + + /// + /// 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. + /// + /// containing bits to append + /// bits from value to append + 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]; + } + } + + /// + /// Toes the bytes. + /// + /// first bit to start writing + /// array to write into. Bytes are written most-significant byte first. This is the opposite + /// of the internal representation, which is exposed by BitArray + /// position in array to start writing + /// how many bytes to write + 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; + } + } + + /// Reverses all bits in the array. + public void reverse() + { + var newBits = new int[bits.Length]; + // reverse all int's first + var len = ((size - 1) >> 5); + var oldBitsLen = len + 1; + for (var i = 0; i < oldBitsLen; i++) + { + var x = (long)bits[i]; + x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1); + x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2); + x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4); + x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8); + x = ((x >> 16) & 0x0000ffffu) | ((x & 0x0000ffffu) << 16); + newBits[len - i] = (int)x; + } + // now correct the int's if the bit size isn't a multiple of 32 + if (size != oldBitsLen * 32) + { + var leftOffset = oldBitsLen * 32 - size; + var mask = 1; + for (var i = 0; i < 31 - leftOffset; i++) + mask = (mask << 1) | 1; + var currentInt = (newBits[0] >> leftOffset) & mask; + for (var i = 1; i < oldBitsLen; i++) + { + var nextInt = newBits[i]; + currentInt |= nextInt << (32 - leftOffset); + newBits[i - 1] = currentInt; + currentInt = (nextInt >> leftOffset) & mask; + } + newBits[oldBitsLen - 1] = currentInt; + } + bits = newBits; + } + + private static int[] makeArray(int size) + { + return new int[(size + 31) >> 5]; + } + + /// + /// Determines whether the specified is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public override bool Equals(Object o) + { + var other = o as BitArray; + if (other == null) + return false; + if (size != other.size) + return false; + for (var index = 0; index < size; index++) + { + if (bits[index] != other.bits[index]) + return false; + } + return true; + } + + /// + /// Returns a hash code for this instance. + /// + /// + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// + public override int GetHashCode() + { + var hash = size; + foreach (var bit in bits) + { + hash = 31 * hash + bit.GetHashCode(); + } + return hash; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override String ToString() + { + var result = new System.Text.StringBuilder(size); + for (int i = 0; i < size; i++) + { + if ((i & 0x07) == 0) + { + result.Append(' '); + } + result.Append(this[i] ? 'X' : '.'); + } + return result.ToString(); + } + + /// + /// Erstellt ein neues Objekt, das eine Kopie der aktuellen Instanz darstellt. + /// + /// + /// Ein neues Objekt, das eine Kopie dieser Instanz darstellt. + /// + public object Clone() + { + return new BitArray((int[])bits.Clone(), size); + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/BitMatrix.cs b/shadowsocks-csharp/3rd/zxing/BitMatrix.cs new file mode 100755 index 00000000..d0378d45 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/BitMatrix.cs @@ -0,0 +1,435 @@ +/* +* 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 +{ + /// + ///

Represents a 2D matrix of bits. In function arguments below, and throughout the common + /// module, x is the column position, and y is the row position. The ordering is always x, y. + /// The origin is at the top-left.

+ ///

Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins + /// with a new int. This is done intentionally so that we can copy out a row into a BitArray very + /// efficiently.

+ ///

The ordering of bits is row-major. Within each int, the least significant bits are used first, + /// meaning they represent lower x values. This is compatible with BitArray's implementation.

+ ///
+ /// Sean Owen + /// dswitkin@google.com (Daniel Switkin) + public sealed partial class BitMatrix + { + private readonly int width; + private readonly int height; + private readonly int rowSize; + private readonly int[] bits; + + /// The width of the matrix + /// + public int Width + { + get + { + return width; + } + + } + /// The height of the matrix + /// + public int Height + { + get + { + return height; + } + + } + /// This method is for compatibility with older code. It's only logical to call if the matrix + /// is square, so I'm throwing if that's not the case. + /// + /// + /// row/column dimension of this matrix + /// + public int Dimension + { + get + { + if (width != height) + { + throw new System.ArgumentException("Can't call getDimension() on a non-square matrix"); + } + return width; + } + + } + + // A helper to construct a square matrix. + public BitMatrix(int dimension) + : this(dimension, dimension) + { + } + + public BitMatrix(int width, int height) + { + if (width < 1 || height < 1) + { + throw new System.ArgumentException("Both dimensions must be greater than 0"); + } + this.width = width; + this.height = height; + this.rowSize = (width + 31) >> 5; + bits = new int[rowSize * height]; + } + + internal BitMatrix(int width, int height, int rowSize, int[] bits) + { + this.width = width; + this.height = height; + this.rowSize = rowSize; + this.bits = bits; + } + + internal BitMatrix(int width, int height, int[] bits) + { + this.width = width; + this.height = height; + this.rowSize = (width + 31) >> 5; + this.bits = bits; + } + + ///

Gets the requested bit, where true means black.

+ /// + ///
+ /// The horizontal component (i.e. which column) + /// + /// The vertical component (i.e. which row) + /// + /// value of given bit in matrix + /// + public bool this[int x, int y] + { + get + { + int offset = y * rowSize + (x >> 5); + return (((int)((uint)(bits[offset]) >> (x & 0x1f))) & 1) != 0; + } + set + { + if (value) + { + int offset = y * rowSize + (x >> 5); + bits[offset] |= 1 << (x & 0x1f); + } + } + } + + ///

Flips the given bit.

+ /// + ///
+ /// The horizontal component (i.e. which column) + /// + /// The vertical component (i.e. which row) + /// + public void flip(int x, int y) + { + int offset = y * rowSize + (x >> 5); + bits[offset] ^= 1 << (x & 0x1f); + } + + /// Clears all bits (sets to false). + public void clear() + { + int max = bits.Length; + for (int i = 0; i < max; i++) + { + bits[i] = 0; + } + } + + ///

Sets a square region of the bit matrix to true.

+ /// + ///
+ /// The horizontal position to begin at (inclusive) + /// + /// The vertical position to begin at (inclusive) + /// + /// The width of the region + /// + /// The height of the region + /// + public void setRegion(int left, int top, int width, int height) + { + if (top < 0 || left < 0) + { + throw new System.ArgumentException("Left and top must be nonnegative"); + } + if (height < 1 || width < 1) + { + throw new System.ArgumentException("Height and width must be at least 1"); + } + int right = left + width; + int bottom = top + height; + if (bottom > this.height || right > this.width) + { + throw new System.ArgumentException("The region must fit inside the matrix"); + } + for (int y = top; y < bottom; y++) + { + int offset = y * rowSize; + for (int x = left; x < right; x++) + { + bits[offset + (x >> 5)] |= 1 << (x & 0x1f); + } + } + } + + /// A fast method to retrieve one row of data from the matrix as a BitArray. + /// + /// + /// The row to retrieve + /// + /// An optional caller-allocated BitArray, will be allocated if null or too small + /// + /// The resulting BitArray - this reference should always be used even when passing + /// your own row + /// + public BitArray getRow(int y, BitArray row) + { + if (row == null || row.Size < width) + { + row = new BitArray(width); + } + else + { + row.clear(); + } + int offset = y * rowSize; + for (int x = 0; x < rowSize; x++) + { + row.setBulk(x << 5, bits[offset + x]); + } + return row; + } + + /// + /// Sets the row. + /// + /// row to set + /// {@link BitArray} to copy from + public void setRow(int y, BitArray row) + { + Array.Copy(row.Array, 0, bits, y * rowSize, rowSize); + } + + /// + /// Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees + /// + public void rotate180() + { + var width = Width; + var height = Height; + var topRow = new BitArray(width); + var bottomRow = new BitArray(width); + for (int i = 0; i < (height + 1)/2; i++) + { + topRow = getRow(i, topRow); + bottomRow = getRow(height - 1 - i, bottomRow); + topRow.reverse(); + bottomRow.reverse(); + setRow(i, bottomRow); + setRow(height - 1 - i, topRow); + } + } + + /// + /// This is useful in detecting the enclosing rectangle of a 'pure' barcode. + /// + /// {left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white + public int[] getEnclosingRectangle() + { + int left = width; + int top = height; + int right = -1; + int bottom = -1; + + for (int y = 0; y < height; y++) + { + for (int x32 = 0; x32 < rowSize; x32++) + { + int theBits = bits[y * rowSize + x32]; + if (theBits != 0) + { + if (y < top) + { + top = y; + } + if (y > bottom) + { + bottom = y; + } + if (x32 * 32 < left) + { + int bit = 0; + while ((theBits << (31 - bit)) == 0) + { + bit++; + } + if ((x32 * 32 + bit) < left) + { + left = x32 * 32 + bit; + } + } + if (x32 * 32 + 31 > right) + { + int bit = 31; + while (((int)((uint)theBits >> bit)) == 0) // (theBits >>> bit) + { + bit--; + } + if ((x32 * 32 + bit) > right) + { + right = x32 * 32 + bit; + } + } + } + } + } + + int widthTmp = right - left; + int heightTmp = bottom - top; + + if (widthTmp < 0 || heightTmp < 0) + { + return null; + } + + return new [] { left, top, widthTmp, heightTmp }; + } + + /// + /// This is useful in detecting a corner of a 'pure' barcode. + /// + /// {x,y} coordinate of top-left-most 1 bit, or null if it is all white + public int[] getTopLeftOnBit() + { + int bitsOffset = 0; + while (bitsOffset < bits.Length && bits[bitsOffset] == 0) + { + bitsOffset++; + } + if (bitsOffset == bits.Length) + { + return null; + } + int y = bitsOffset / rowSize; + int x = (bitsOffset % rowSize) << 5; + + int theBits = bits[bitsOffset]; + int bit = 0; + while ((theBits << (31 - bit)) == 0) + { + bit++; + } + x += bit; + return new[] { x, y }; + } + + public int[] getBottomRightOnBit() + { + int bitsOffset = bits.Length - 1; + while (bitsOffset >= 0 && bits[bitsOffset] == 0) + { + bitsOffset--; + } + if (bitsOffset < 0) + { + return null; + } + + int y = bitsOffset / rowSize; + int x = (bitsOffset % rowSize) << 5; + + int theBits = bits[bitsOffset]; + int bit = 31; + + while (((int)((uint)theBits >> bit)) == 0) // (theBits >>> bit) + { + bit--; + } + x += bit; + + return new int[] { x, y }; + } + + public override bool Equals(object obj) + { + if (!(obj is BitMatrix)) + { + return false; + } + BitMatrix other = (BitMatrix)obj; + if (width != other.width || height != other.height || + rowSize != other.rowSize || bits.Length != other.bits.Length) + { + return false; + } + for (int i = 0; i < bits.Length; i++) + { + if (bits[i] != other.bits[i]) + { + return false; + } + } + return true; + } + + public override int GetHashCode() + { + int hash = width; + hash = 31 * hash + width; + hash = 31 * hash + height; + hash = 31 * hash + rowSize; + foreach (var bit in bits) + { + hash = 31 * hash + bit.GetHashCode(); + } + return hash; + } + + public override String ToString() + { + var result = new System.Text.StringBuilder(height * (width + 1)); + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + result.Append(this[x, y] ? "X " : " "); + } +#if WindowsCE + result.Append("\r\n"); +#else + result.AppendLine(""); +#endif + } + return result.ToString(); + } + + public object Clone() + { + return new BitMatrix(width, height, rowSize, (int[])bits.Clone()); + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/BlockPair.cs b/shadowsocks-csharp/3rd/zxing/BlockPair.cs new file mode 100755 index 00000000..b1afff46 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/BlockPair.cs @@ -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; } + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/ByteMatrix.cs b/shadowsocks-csharp/3rd/zxing/ByteMatrix.cs new file mode 100755 index 00000000..e3d372fd --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/ByteMatrix.cs @@ -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 +{ + /// + /// 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. + /// + /// dswitkin@google.com (Daniel Switkin) + public sealed class ByteMatrix + { + private readonly byte[][] bytes; + private readonly int width; + private readonly int height; + + /// + /// Initializes a new instance of the class. + /// + /// The width. + /// The height. + 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; + } + + /// + /// Gets the height. + /// + public int Height + { + get { return height; } + } + + /// + /// Gets the width. + /// + public int Width + { + get { return width; } + } + + /// + /// Gets or sets the with the specified x. + /// + public int this[int x, int y] + { + get { return bytes[y][x]; } + set { bytes[y][x] = (byte)value; } + } + + /// + /// an internal representation as bytes, in row-major order. array[y][x] represents point (x,y) + /// + public byte[][] Array + { + get { return bytes; } + } + + /// + /// Sets the specified x. + /// + /// The x. + /// The y. + /// The value. + public void set(int x, int y, byte value) + { + bytes[y][x] = value; + } + + /// + /// Sets the specified x. + /// + /// The x. + /// The y. + /// if set to true [value]. + public void set(int x, int y, bool value) + { + bytes[y][x] = (byte)(value ? 1 : 0); + } + + /// + /// Clears the specified value. + /// + /// The value. + public void clear(byte value) + { + for (int y = 0; y < height; ++y) + { + for (int x = 0; x < width; ++x) + { + bytes[y][x] = value; + } + } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + 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(); + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs b/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs new file mode 100755 index 00000000..01b17f8c --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs @@ -0,0 +1,131 @@ +/* +* 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 +{ + /// + /// These are a set of hints that you may pass to Writers to specify their behavior. + /// + /// dswitkin@google.com (Daniel Switkin) + public enum EncodeHintType + { + /// + /// Specifies the width of the barcode image + /// type: + /// + WIDTH, + + /// + /// Specifies the height of the barcode image + /// type: + /// + HEIGHT, + + /// + /// Don't put the content string into the output image. + /// type: + /// + PURE_BARCODE, + + /// + /// Specifies what degree of error correction to use, for example in QR Codes. + /// Type depends on the encoder. For example for QR codes it's type + /// + /// For Aztec it is of type , representing the minimal percentage of error correction words. + /// Note: an Aztec symbol should have a minimum of 25% EC words. + /// For PDF417 it is of type or (between 0 and 8), + /// + ERROR_CORRECTION, + + /// + /// Specifies what character encoding to use where applicable. + /// type: + /// + CHARACTER_SET, + + /// + /// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary + /// by format; for example it controls margin before and after the barcode horizontally for + /// most 1D formats. + /// type: + /// + MARGIN, + + /// + /// Specifies whether to use compact mode for PDF417. + /// type: + /// + PDF417_COMPACT, + + /// + /// Specifies what compaction mode to use for PDF417. + /// type: + /// + PDF417_COMPACTION, + + /// + /// Specifies the minimum and maximum number of rows and columns for PDF417. + /// type: + /// + PDF417_DIMENSIONS, + + /// + /// Don't append ECI segment. + /// That is against the specification of QR Code but some + /// readers have problems if the charset is switched from + /// ISO-8859-1 (default) to UTF-8 with the necessary ECI segment. + /// If you set the property to true you can use UTF-8 encoding + /// and the ECI segment is omitted. + /// type: + /// + DISABLE_ECI, + + /// + /// Specifies the matrix shape for Data Matrix (type ) + /// + DATA_MATRIX_SHAPE, + + /// + /// Specifies a minimum barcode size (type ). Only applicable to Data Matrix now. + /// + MIN_SIZE, + + /// + /// Specifies a maximum barcode size (type ). Only applicable to Data Matrix now. + /// + MAX_SIZE, + + /// + /// if true, don't switch to codeset C for numbers + /// + CODE128_FORCE_CODESET_B, + + /// + /// Specifies the default encodation for Data Matrix (type ) + /// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown. + /// standard value: Encodation.ASCII + /// + DATA_MATRIX_DEFAULT_ENCODATION, + + /// + /// Specifies the required number of layers for an Aztec code: + /// a negative number (-1, -2, -3, -4) specifies a compact Aztec code + /// 0 indicates to use the minimum number of layers (the default) + /// a positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code + /// + AZTEC_LAYERS, + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/Encoder.cs b/shadowsocks-csharp/3rd/zxing/Encoder.cs new file mode 100755 index 00000000..694d6ca4 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/Encoder.cs @@ -0,0 +1,762 @@ +/* +* 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 +{ + /// + /// + /// satorux@google.com (Satoru Takabayashi) - creator + /// dswitkin@google.com (Daniel Switkin) - ported from C++ + public static class Encoder + { + + // The original table is defined in the table 5 of JISX0510:2004 (p.19). + private static readonly int[] ALPHANUMERIC_TABLE = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f + }; + + 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); + } + + /// + /// 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. + /// + /// text to encode + /// error correction level to use + /// representing the encoded QR code + public static QRCode encode(String content, ErrorCorrectionLevel ecLevel) + { + return encode(content, ecLevel, null); + } + + /// + /// Encodes the specified content. + /// + /// The content. + /// The ec level. + /// The hints. + /// + public static QRCode encode(String content, + ErrorCorrectionLevel ecLevel, + IDictionary hints) + { + // Determine what character encoding has been specified by the caller, if any +#if !SILVERLIGHT || WINDOWS_PHONE + String encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; + if (encoding == null) + { + 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 = chooseMode(content, encoding); + + // 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; + } + + /// + /// Gets the alphanumeric code. + /// + /// The code. + /// the code point of the table used in alphanumeric mode or + /// -1 if there is no corresponding code in the table. + internal static int getAlphanumericCode(int code) + { + if (code < ALPHANUMERIC_TABLE.Length) + { + return ALPHANUMERIC_TABLE[code]; + } + return -1; + } + + /// + /// Chooses the mode. + /// + /// The content. + /// + public static Mode chooseMode(String content) + { + return chooseMode(content, null); + } + + /// + /// Choose the best mode by examining the content. Note that 'encoding' is used as a hint; + /// if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. + /// + /// The content. + /// The encoding. + /// + private static Mode chooseMode(String content, String encoding) + { + if ("Shift_JIS".Equals(encoding)) + { + + // Choose Kanji mode if all input are double-byte characters + return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE; + } + bool hasNumeric = false; + bool hasAlphanumeric = false; + for (int i = 0; i < content.Length; ++i) + { + char c = content[i]; + if (c >= '0' && c <= '9') + { + hasNumeric = true; + } + else if (getAlphanumericCode(c) != -1) + { + hasAlphanumeric = true; + } + else + { + return Mode.BYTE; + } + } + if (hasAlphanumeric) + { + + return Mode.ALPHANUMERIC; + } + if (hasNumeric) + { + + return Mode.NUMERIC; + } + return Mode.BYTE; + } + + private static bool isOnlyDoubleByteKanji(String content) + { + byte[] bytes; + try + { + bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); + } + catch (Exception ) + { + return false; + } + int length = bytes.Length; + if (length % 2 != 0) + { + return false; + } + for (int i = 0; i < length; i += 2) + { + + + int byte1 = bytes[i] & 0xFF; + if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) + { + + return false; + } + } + return true; + } + + 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"); + } + + /// + /// Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24). + /// + /// The num data bytes. + /// The bits. + 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"); + } + } + + /// + /// 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) + /// + /// The num total bytes. + /// The num data bytes. + /// The num RS blocks. + /// The block ID. + /// The num data bytes in block. + /// The num EC bytes in block. + 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; + } + } + + /// + /// 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. + /// + /// The bits. + /// The num total bytes. + /// The num data bytes. + /// The num RS blocks. + /// + 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(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; + } + + /// + /// Append mode info. On success, store the result in "bits". + /// + /// The mode. + /// The bits. + internal static void appendModeInfo(Mode mode, BitArray bits) + { + bits.appendBits(mode.Bits, 4); + } + + + /// + /// Append length info. On success, store the result in "bits". + /// + /// The num letters. + /// The version. + /// The mode. + /// The bits. + 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); + } + + /// + /// Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits". + /// + /// The content. + /// The mode. + /// The bits. + /// The encoding. + internal static void appendBytes(String content, + Mode mode, + BitArray bits, + String encoding) + { + if (mode.Equals(Mode.NUMERIC)) + appendNumericBytes(content, bits); + else + if (mode.Equals(Mode.ALPHANUMERIC)) + appendAlphanumericBytes(content, bits); + else + if (mode.Equals(Mode.BYTE)) + append8BitBytes(content, bits, encoding); + else + if (mode.Equals(Mode.KANJI)) + appendKanjiBytes(content, bits); + else + throw new Exception("Invalid mode: " + mode); + } + + internal static void appendNumericBytes(String content, BitArray bits) + { + int length = content.Length; + + int i = 0; + while (i < length) + { + int num1 = content[i] - '0'; + if (i + 2 < length) + { + // Encode three numeric letters in ten bits. + int num2 = content[i + 1] - '0'; + int num3 = content[i + 2] - '0'; + bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); + i += 3; + } + else if (i + 1 < length) + { + // Encode two numeric letters in seven bits. + int num2 = content[i + 1] - '0'; + bits.appendBits(num1 * 10 + num2, 7); + i += 2; + } + else + { + // Encode one numeric letter in four bits. + bits.appendBits(num1, 4); + i++; + } + } + } + + internal static void appendAlphanumericBytes(String content, BitArray bits) + { + int length = content.Length; + + int i = 0; + while (i < length) + { + int code1 = getAlphanumericCode(content[i]); + if (code1 == -1) + { + throw new Exception(); + } + if (i + 1 < length) + { + int code2 = getAlphanumericCode(content[i + 1]); + if (code2 == -1) + { + throw new Exception(); + } + // Encode two alphanumeric letters in 11 bits. + bits.appendBits(code1 * 45 + code2, 11); + i += 2; + } + else + { + // Encode one alphanumeric letter in six bits. + bits.appendBits(code1, 6); + i++; + } + } + } + + 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); + } + } + + internal static void appendKanjiBytes(String content, BitArray bits) + { + byte[] bytes; + try + { + bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); + } + catch (Exception uee) + { + throw new Exception(uee.Message, uee); + } + int length = bytes.Length; + for (int i = 0; i < length; i += 2) + { + int byte1 = bytes[i] & 0xFF; + int byte2 = bytes[i + 1] & 0xFF; + int code = (byte1 << 8) | byte2; + int subtracted = -1; + if (code >= 0x8140 && code <= 0x9ffc) + { + + subtracted = code - 0x8140; + } + else if (code >= 0xe040 && code <= 0xebbf) + { + subtracted = code - 0xc140; + } + if (subtracted == -1) + { + + throw new Exception("Invalid byte sequence"); + } + int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); + bits.appendBits(encoded, 13); + } + } + + /* + 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); + } + * */ + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs b/shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs new file mode 100755 index 00000000..f3b49347 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/ErrorCorrectionLevel.cs @@ -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 +{ + /// + ///

See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels + /// defined by the QR code standard.

+ ///
+ /// Sean Owen + public sealed class ErrorCorrectionLevel + { + /// L = ~7% correction + public static readonly ErrorCorrectionLevel L = new ErrorCorrectionLevel(0, 0x01, "L"); + /// M = ~15% correction + public static readonly ErrorCorrectionLevel M = new ErrorCorrectionLevel(1, 0x00, "M"); + /// Q = ~25% correction + public static readonly ErrorCorrectionLevel Q = new ErrorCorrectionLevel(2, 0x03, "Q"); + /// H = ~30% correction + 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; + } + + /// + /// Gets the bits. + /// + public int Bits + { + get + { + return bits; + } + } + + /// + /// Gets the name. + /// + public String Name + { + get + { + return name; + } + } + + private readonly int ordinal_Renamed_Field; + private readonly String name; + + /// + /// Ordinals this instance. + /// + /// + public int ordinal() + { + return ordinal_Renamed_Field; + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override String ToString() + { + return name; + } + + /// + /// Fors the bits. + /// + /// int containing the two bits encoding a QR Code's error correction level + /// + /// representing the encoded error correction level + /// + public static ErrorCorrectionLevel forBits(int bits) + { + if (bits < 0 || bits >= FOR_BITS.Length) + { + throw new ArgumentException(); + } + return FOR_BITS[bits]; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/FormatInformation.cs b/shadowsocks-csharp/3rd/zxing/FormatInformation.cs new file mode 100755 index 00000000..88b5045e --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/FormatInformation.cs @@ -0,0 +1,197 @@ +/* +* 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 +{ + + ///

Encapsulates a QR Code's format information, including the data mask used and + /// error correction level.

+ /// + ///
+ /// Sean Owen + /// + /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source + /// + /// + /// + /// + /// + sealed class FormatInformation + { + private const int FORMAT_INFO_MASK_QR = 0x5412; + + /// See ISO 18004:2006, Annex C, Table C.1 + private static readonly int[][] FORMAT_INFO_DECODE_LOOKUP = new int[][] + { + new [] { 0x5412, 0x00 }, + new [] { 0x5125, 0x01 }, + new [] { 0x5E7C, 0x02 }, + new [] { 0x5B4B, 0x03 }, + new [] { 0x45F9, 0x04 }, + new [] { 0x40CE, 0x05 }, + new [] { 0x4F97, 0x06 }, + new [] { 0x4AA0, 0x07 }, + new [] { 0x77C4, 0x08 }, + new [] { 0x72F3, 0x09 }, + new [] { 0x7DAA, 0x0A }, + new [] { 0x789D, 0x0B }, + new [] { 0x662F, 0x0C }, + new [] { 0x6318, 0x0D }, + new [] { 0x6C41, 0x0E }, + new [] { 0x6976, 0x0F }, + new [] { 0x1689, 0x10 }, + new [] { 0x13BE, 0x11 }, + new [] { 0x1CE7, 0x12 }, + new [] { 0x19D0, 0x13 }, + new [] { 0x0762, 0x14 }, + new [] { 0x0255, 0x15 }, + new [] { 0x0D0C, 0x16 }, + new [] { 0x083B, 0x17 }, + new [] { 0x355F, 0x18 }, + new [] { 0x3068, 0x19 }, + new [] { 0x3F31, 0x1A }, + new [] { 0x3A06, 0x1B }, + new [] { 0x24B4, 0x1C }, + new [] { 0x2183, 0x1D }, + new [] { 0x2EDA, 0x1E }, + new [] { 0x2BED, 0x1F } + }; + + /// Offset i holds the number of 1 bits in the binary representation of i + private static readonly int[] BITS_SET_IN_HALF_BYTE = new [] + { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; + + private readonly ErrorCorrectionLevel errorCorrectionLevel; + private readonly byte dataMask; + + private FormatInformation(int formatInfo) + { + // Bits 3,4 + errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); + // Bottom 3 bits + dataMask = (byte)(formatInfo & 0x07); + } + + internal static int numBitsDiffering(int a, int b) + { + a ^= b; // a now has a 1 bit exactly where its bit differs with b's + // Count bits set quickly with a series of lookups: + return BITS_SET_IN_HALF_BYTE[a & 0x0F] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 4)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 8)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 12)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 16)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 20)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 24)) & 0x0F)] + + BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 28)) & 0x0F)]; + } + + /// + /// Decodes the format information. + /// + /// format info indicator, with mask still applied + /// The masked format info2. + /// + /// information about the format it specifies, or null + /// if doesn't seem to match any known pattern + /// + internal static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) + { + FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); + if (formatInfo != null) + { + return formatInfo; + } + // Should return null, but, some QR codes apparently + // do not mask this info. Try again by actually masking the pattern + // first + return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR, + maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR); + } + + private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) + { + // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing + int bestDifference = Int32.MaxValue; + int bestFormatInfo = 0; + foreach (var decodeInfo in FORMAT_INFO_DECODE_LOOKUP) + { + int targetInfo = decodeInfo[0]; + if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) + { + // Found an exact match + return new FormatInformation(decodeInfo[1]); + } + int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo); + if (bitsDifference < bestDifference) + { + bestFormatInfo = decodeInfo[1]; + bestDifference = bitsDifference; + } + if (maskedFormatInfo1 != maskedFormatInfo2) + { + // also try the other option + bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo); + if (bitsDifference < bestDifference) + { + bestFormatInfo = decodeInfo[1]; + bestDifference = bitsDifference; + } + } + } + // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits + // differing means we found a match + if (bestDifference <= 3) + { + return new FormatInformation(bestFormatInfo); + } + return null; + } + + internal ErrorCorrectionLevel ErrorCorrectionLevel + { + get + { + return errorCorrectionLevel; + } + } + + internal byte DataMask + { + get + { + return dataMask; + } + } + + public override int GetHashCode() + { + return (errorCorrectionLevel.ordinal() << 3) | dataMask; + } + + public override bool Equals(Object o) + { + if (!(o is FormatInformation)) + { + return false; + } + var other = (FormatInformation)o; + return errorCorrectionLevel == other.errorCorrectionLevel && dataMask == other.dataMask; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/GenericGF.cs b/shadowsocks-csharp/3rd/zxing/GenericGF.cs new file mode 100755 index 00000000..8a2835ea --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/GenericGF.cs @@ -0,0 +1,210 @@ +/* + * 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 +{ + /// + ///

This class contains utility methods for performing mathematical operations over + /// the Galois Fields. Operations use a given primitive polynomial in calculations.

+ ///

Throughout this package, elements of the GF are represented as an {@code int} + /// for convenience and speed (but at the cost of memory). + ///

+ ///
+ /// Sean Owen + public sealed class GenericGF + { + public static GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 + public static GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1 + public static GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1 + public static GenericGF AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1 + public static GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 + public static GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 + public static GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256; + public static GenericGF MAXICODE_FIELD_64 = AZTEC_DATA_6; + + private int[] expTable; + private int[] logTable; + private GenericGFPoly zero; + private GenericGFPoly one; + private readonly int size; + private readonly int primitive; + private readonly int generatorBase; + + /// + /// Create a representation of GF(size) using the given primitive polynomial. + /// + /// irreducible polynomial whose coefficients are represented by + /// * the bits of an int, where the least-significant bit represents the constant + /// * coefficient + /// the size of the field + /// 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. + 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; + } + } + + internal GenericGFPoly One + { + get + { + return one; + } + } + + /// + /// Builds the monomial. + /// + /// The degree. + /// The coefficient. + /// the monomial representing coefficient * x^degree + 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); + } + + /// + /// Implements both addition and subtraction -- they are the same in GF(size). + /// + /// sum/difference of a and b + static internal int addOrSubtract(int a, int b) + { + return a ^ b; + } + + /// + /// Exps the specified a. + /// + /// 2 to the power of a in GF(size) + internal int exp(int a) + { + return expTable[a]; + } + + /// + /// Logs the specified a. + /// + /// A. + /// base 2 log of a in GF(size) + internal int log(int a) + { + if (a == 0) + { + throw new ArgumentException(); + } + return logTable[a]; + } + + /// + /// Inverses the specified a. + /// + /// multiplicative inverse of a + internal int inverse(int a) + { + if (a == 0) + { + throw new ArithmeticException(); + } + return expTable[size - logTable[a] - 1]; + } + + /// + /// Multiplies the specified a with b. + /// + /// A. + /// The b. + /// product of a and b in GF(size) + internal int multiply(int a, int b) + { + if (a == 0 || b == 0) + { + return 0; + } + return expTable[(logTable[a] + logTable[b]) % (size - 1)]; + } + + /// + /// Gets the size. + /// + public int Size + { + get { return size; } + } + + /// + /// Gets the generator base. + /// + public int GeneratorBase + { + get { return generatorBase; } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + override public String ToString() + { + return "GF(0x" + primitive.ToString("X") + ',' + size + ')'; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs b/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs new file mode 100755 index 00000000..8307a1dd --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs @@ -0,0 +1,331 @@ +/* + * 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 +{ + /// + ///

Represents a polynomial whose coefficients are elements of a GF. + /// Instances of this class are immutable.

+ ///

Much credit is due to William Rucklidge since portions of this code are an indirect + /// port of his C++ Reed-Solomon implementation.

+ ///
+ /// Sean Owen + internal sealed class GenericGFPoly + { + private readonly GenericGF field; + private readonly int[] coefficients; + + /// + /// Initializes a new instance of the class. + /// + /// the {@link GenericGF} instance representing the field to use + /// to perform computations + /// coefficients as ints representing elements of GF(size), arranged + /// from most significant (highest-power term) coefficient to least significant + /// 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") + 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; } + } + + /// + /// degree of this polynomial + /// + internal int Degree + { + get + { + return coefficients.Length - 1; + } + } + + /// + /// Gets a value indicating whether this is zero. + /// + /// true iff this polynomial is the monomial "0" + internal bool isZero + { + get { return coefficients[0] == 0; } + } + + /// + /// coefficient of x^degree term in this polynomial + /// + /// The degree. + /// coefficient of x^degree term in this polynomial + internal int getCoefficient(int degree) + { + return coefficients[coefficients.Length - 1 - degree]; + } + + /// + /// evaluation of this polynomial at a given point + /// + /// A. + /// evaluation of this polynomial at a given point + internal int evaluateAt(int a) + { + int result = 0; + if (a == 0) + { + // Just return the x^0 coefficient + return getCoefficient(0); + } + int size = coefficients.Length; + if (a == 1) + { + // Just the sum of the coefficients + foreach (var coefficient in coefficients) + { + result = GenericGF.addOrSubtract(result, coefficient); + } + return result; + } + result = coefficients[0]; + for (int i = 1; i < size; i++) + { + result = GenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); + } + return result; + } + + 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 multiply(int scalar) + { + if (scalar == 0) + { + return field.Zero; + } + if (scalar == 1) + { + return this; + } + int size = coefficients.Length; + int[] product = new int[size]; + for (int i = 0; i < size; i++) + { + product[i] = field.multiply(coefficients[i], scalar); + } + 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 }; + } + + public override String ToString() + { + StringBuilder result = new StringBuilder(8 * Degree); + for (int degree = Degree; degree >= 0; degree--) + { + int coefficient = getCoefficient(degree); + if (coefficient != 0) + { + if (coefficient < 0) + { + result.Append(" - "); + coefficient = -coefficient; + } + else + { + if (result.Length > 0) + { + result.Append(" + "); + } + } + if (degree == 0 || coefficient != 1) + { + int alphaPower = field.log(coefficient); + if (alphaPower == 0) + { + result.Append('1'); + } + else if (alphaPower == 1) + { + result.Append('a'); + } + else + { + result.Append("a^"); + result.Append(alphaPower); + } + } + if (degree != 0) + { + if (degree == 1) + { + result.Append('x'); + } + else + { + result.Append("x^"); + result.Append(degree); + } + } + } + } + return result.ToString(); + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/MaskUtil.cs b/shadowsocks-csharp/3rd/zxing/MaskUtil.cs new file mode 100755 index 00000000..24e85cc1 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/MaskUtil.cs @@ -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 +{ + /// + /// + /// + /// Satoru Takabayashi + /// Daniel Switkin + /// Sean Owen + 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; + + /// + /// 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. + /// + /// The matrix. + /// + public static int applyMaskPenaltyRule1(ByteMatrix matrix) + { + return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false); + } + + /// + /// 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. + /// + /// The matrix. + /// + 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; + } + + /// + /// 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). + /// + /// The matrix. + /// + 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; + } + + /// + /// 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. + /// + /// The matrix. + /// + 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; + } + + /// + /// Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask + /// pattern conditions. + /// + /// The mask pattern. + /// The x. + /// The y. + /// + 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; + } + + /// + /// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both + /// vertical and horizontal orders respectively. + /// + /// The matrix. + /// if set to true [is horizontal]. + /// + 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; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/MatrixUtil.cs b/shadowsocks-csharp/3rd/zxing/MatrixUtil.cs new file mode 100755 index 00000000..ffd9c7b4 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/MatrixUtil.cs @@ -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 +{ + /// + /// + /// + /// + /// satorux@google.com (Satoru Takabayashi) - creator + /// + 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; + + /// + /// 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. + /// + /// The matrix. + public static void clearMatrix(ByteMatrix matrix) + { + matrix.clear(2); + } + + /// + /// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On + /// success, store the result in "matrix" and return true. + /// + /// The data bits. + /// The ec level. + /// The version. + /// The mask pattern. + /// The matrix. + 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); + } + + /// + /// 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 + /// + /// The version. + /// The matrix. + 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); + } + + /// + /// Embed type information. On success, modify the matrix. + /// + /// The ec level. + /// The mask pattern. + /// The matrix. + 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; + } + } + } + + /// + /// 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. + /// + /// The version. + /// The matrix. + 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; + } + } + } + + /// + /// 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. + /// + /// The data bits. + /// The mask pattern. + /// The matrix. + 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); + } + } + + /// + /// 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 + /// + /// The value_ renamed. + /// + public static int findMSBSet(int value_Renamed) + { + int numDigits = 0; + while (value_Renamed != 0) + { + value_Renamed = (int)((uint)value_Renamed >> 1); + ++numDigits; + } + return numDigits; + } + + /// + /// 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. + /// + /// The value. + /// The poly. + /// + 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; + } + + /// + /// 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. + /// + /// The ec level. + /// The mask pattern. + /// The bits. + 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); + } + } + + /// + /// 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. + /// + /// The version. + /// The bits. + 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); + } + } + + /// + /// Check if "value" is empty. + /// + /// The value. + /// + /// true if the specified value is empty; otherwise, false. + /// + 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; + } + } + } + + /// + /// Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46) + /// + /// The matrix. + 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; + } + } + + /// + /// 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. + /// + /// The x start. + /// The y start. + /// The matrix. + 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]; + } + } + } + + /// + /// Embed position detection patterns and surrounding vertical/horizontal separators. + /// + /// The matrix. + 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); + } + + /// + /// Embed position adjustment patterns if need be. + /// + /// The version. + /// The matrix. + 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); + } + } + } + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/Mode.cs b/shadowsocks-csharp/3rd/zxing/Mode.cs new file mode 100755 index 00000000..548ea6d7 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/Mode.cs @@ -0,0 +1,179 @@ +/* +* 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 +{ + /// + ///

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.

+ ///
+ /// Sean Owen + public sealed class Mode + { + /// + /// Gets the name. + /// + public String Name + { + get + { + return name; + } + } + + // No, we can't use an enum here. J2ME doesn't support it. + + /// + /// + /// + public static readonly Mode TERMINATOR = new Mode(new int[] { 0, 0, 0 }, 0x00, "TERMINATOR"); // Not really a mode... + /// + /// + /// + public static readonly Mode NUMERIC = new Mode(new int[] { 10, 12, 14 }, 0x01, "NUMERIC"); + /// + /// + /// + public static readonly Mode ALPHANUMERIC = new Mode(new int[] { 9, 11, 13 }, 0x02, "ALPHANUMERIC"); + /// + /// + /// + public static readonly Mode STRUCTURED_APPEND = new Mode(new int[] { 0, 0, 0 }, 0x03, "STRUCTURED_APPEND"); // Not supported + /// + /// + /// + public static readonly Mode BYTE = new Mode(new int[] { 8, 16, 16 }, 0x04, "BYTE"); + /// + /// + /// + public static readonly Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply + /// + /// + /// + public static readonly Mode KANJI = new Mode(new int[] { 8, 10, 12 }, 0x08, "KANJI"); + /// + /// + /// + public static readonly Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION"); + /// + /// + /// + public static readonly Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION"); + /// See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. + public static readonly Mode HANZI = new Mode(new int[] { 8, 10, 12 }, 0x0D, "HANZI"); + + 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; + } + + /// + /// Fors the bits. + /// + /// four bits encoding a QR Code data mode + /// + /// encoded by these bits + /// + /// if bits do not correspond to a known mode + public static Mode forBits(int bits) + { + switch (bits) + { + case 0x0: + return TERMINATOR; + case 0x1: + return NUMERIC; + case 0x2: + return ALPHANUMERIC; + case 0x3: + return STRUCTURED_APPEND; + case 0x4: + return BYTE; + case 0x5: + return FNC1_FIRST_POSITION; + case 0x7: + return ECI; + case 0x8: + return KANJI; + case 0x9: + return FNC1_SECOND_POSITION; + case 0xD: + // 0xD is defined in GBT 18284-2000, may not be supported in foreign country + return HANZI; + default: + throw new ArgumentException(); + } + } + + /// version in question + /// + /// 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} + /// + 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]; + } + + /// + /// Gets the bits. + /// + public int Bits + { + get + { + return bits; + } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override String ToString() + { + return name; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/QRCode.cs b/shadowsocks-csharp/3rd/zxing/QRCode.cs new file mode 100755 index 00000000..312f94ef --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/QRCode.cs @@ -0,0 +1,125 @@ +/* +* 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 +{ + /// satorux@google.com (Satoru Takabayashi) - creator + /// dswitkin@google.com (Daniel Switkin) - ported from C++ + public class QRCode + { + /// + /// + /// + public static int NUM_MASK_PATTERNS = 8; + + /// + /// Initializes a new instance of the class. + /// + public QRCode() + { + MaskPattern = -1; + } + + /// + /// Gets or sets the mode. + /// + /// + /// The mode. + /// + public Mode Mode { get; set; } + + /// + /// Gets or sets the EC level. + /// + /// + /// The EC level. + /// + public ErrorCorrectionLevel ECLevel { get; set; } + + /// + /// Gets or sets the version. + /// + /// + /// The version. + /// + public Version Version { get; set; } + + /// + /// Gets or sets the mask pattern. + /// + /// + /// The mask pattern. + /// + public int MaskPattern { get; set; } + + /// + /// Gets or sets the matrix. + /// + /// + /// The matrix. + /// + public ByteMatrix Matrix { get; set; } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override String ToString() + { + var result = new StringBuilder(200); + result.Append("<<\n"); + result.Append(" mode: "); + result.Append(Mode); + result.Append("\n ecLevel: "); + result.Append(ECLevel); + result.Append("\n version: "); + if (Version == null) + result.Append("null"); + else + result.Append(Version); + result.Append("\n maskPattern: "); + result.Append(MaskPattern); + if (Matrix == null) + { + result.Append("\n matrix: null\n"); + } + else + { + result.Append("\n matrix:\n"); + result.Append(Matrix.ToString()); + } + result.Append(">>\n"); + return result.ToString(); + } + + /// + /// Check if "mask_pattern" is valid. + /// + /// The mask pattern. + /// + /// true if [is valid mask pattern] [the specified mask pattern]; otherwise, false. + /// + public static bool isValidMaskPattern(int maskPattern) + { + return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs b/shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs new file mode 100755 index 00000000..78aca71d --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/ReedSolomonEncoder.cs @@ -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 +{ + /// + /// Implements Reed-Solomon encoding, as the name implies. + /// + /// Sean Owen + /// William Rucklidge + public sealed class ReedSolomonEncoder + { + private readonly GenericGF field; + private readonly IList cachedGenerators; + + public ReedSolomonEncoder(GenericGF field) + { + this.field = field; + this.cachedGenerators = new List(); + 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); + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/Version.cs b/shadowsocks-csharp/3rd/zxing/Version.cs new file mode 100755 index 00000000..1404a709 --- /dev/null +++ b/shadowsocks-csharp/3rd/zxing/Version.cs @@ -0,0 +1,685 @@ +/* +* 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 +{ + /// + /// See ISO 18004:2006 Annex D + /// + /// Sean Owen + public sealed class Version + { + /// See ISO 18004:2006 Annex D. + /// Element i represents the raw version bits that specify version i + 7 + /// + private static readonly int[] VERSION_DECODE_INFO = new[] + { + 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, + 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, + 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, + 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, + 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, + 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, + 0x2542E, 0x26A64, 0x27541, 0x28C69 + }; + + 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; + } + + /// + /// Gets the version number. + /// + public int VersionNumber + { + get + { + return versionNumber; + } + + } + + /// + /// Gets the alignment pattern centers. + /// + public int[] AlignmentPatternCenters + { + get + { + return alignmentPatternCenters; + } + + } + + /// + /// Gets the total codewords. + /// + public int TotalCodewords + { + get + { + return totalCodewords; + } + + } + + /// + /// Gets the dimension for version. + /// + public int DimensionForVersion + { + get + { + return 17 + 4 * versionNumber; + } + + } + + /// + /// Gets the EC blocks for level. + /// + /// The ec level. + /// + public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) + { + return ecBlocks[ecLevel.ordinal()]; + } + + ///

Deduces version information purely from QR Code dimensions.

+ /// + ///
+ /// dimension in modules + /// + /// for a QR Code of that dimension or null + public static Version getProvisionalVersionForDimension(int dimension) + { + if (dimension % 4 != 1) + { + return null; + } + try + { + return getVersionForNumber((dimension - 17) >> 2); + } + catch (ArgumentException) + { + return null; + } + } + + /// + /// Gets the version for number. + /// + /// The version number. + /// + public static Version getVersionForNumber(int versionNumber) + { + if (versionNumber < 1 || versionNumber > 40) + { + throw new ArgumentException(); + } + return VERSIONS[versionNumber - 1]; + } + + internal static Version decodeVersionInformation(int versionBits) + { + int bestDifference = Int32.MaxValue; + int bestVersion = 0; + for (int i = 0; i < VERSION_DECODE_INFO.Length; i++) + { + int targetVersion = VERSION_DECODE_INFO[i]; + // Do the version info bits match exactly? done. + if (targetVersion == versionBits) + { + return getVersionForNumber(i + 7); + } + // Otherwise see if this is the closest to a real version info bit string + // we have seen so far + int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); + if (bitsDifference < bestDifference) + { + bestVersion = i + 7; + bestDifference = bitsDifference; + } + } + // We can tolerate up to 3 bits of error since no two version info codewords will + // differ in less than 8 bits. + if (bestDifference <= 3) + { + return getVersionForNumber(bestVersion); + } + // If we didn't find a close enough match, fail + return null; + } + + /// See ISO 18004:2006 Annex E + internal BitMatrix buildFunctionPattern() + { + int dimension = DimensionForVersion; + BitMatrix bitMatrix = new BitMatrix(dimension); + + // Top left finder pattern + separator + format + bitMatrix.setRegion(0, 0, 9, 9); + // Top right finder pattern + separator + format + bitMatrix.setRegion(dimension - 8, 0, 8, 9); + // Bottom left finder pattern + separator + format + bitMatrix.setRegion(0, dimension - 8, 9, 8); + + // Alignment patterns + int max = alignmentPatternCenters.Length; + for (int x = 0; x < max; x++) + { + int i = alignmentPatternCenters[x] - 2; + for (int y = 0; y < max; y++) + { + if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) + { + // No alignment patterns near the three finder paterns + continue; + } + bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5); + } + } + + // Vertical timing pattern + bitMatrix.setRegion(6, 9, 1, dimension - 17); + // Horizontal timing pattern + bitMatrix.setRegion(9, 6, dimension - 17, 1); + + if (versionNumber > 6) + { + // Version info, top right + bitMatrix.setRegion(dimension - 11, 0, 3, 6); + // Version info, bottom left + bitMatrix.setRegion(0, dimension - 11, 6, 3); + } + + return bitMatrix; + } + + ///

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.

+ ///
+ 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; + } + + /// + /// Gets the EC codewords per block. + /// + public int ECCodewordsPerBlock + { + get + { + return ecCodewordsPerBlock; + } + } + + /// + /// Gets the num blocks. + /// + public int NumBlocks + { + get + { + int total = 0; + foreach (var ecBlock in ecBlocks) + { + total += ecBlock.Count; + } + return total; + } + } + + /// + /// Gets the total EC codewords. + /// + public int TotalECCodewords + { + get + { + return ecCodewordsPerBlock * NumBlocks; + } + } + + /// + /// Gets the EC blocks. + /// + /// + public ECB[] getECBlocks() + { + return ecBlocks; + } + } + + ///

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.

+ ///
+ public sealed class ECB + { + private readonly int count; + private readonly int dataCodewords; + + internal ECB(int count, int dataCodewords) + { + this.count = count; + this.dataCodewords = dataCodewords; + } + + /// + /// Gets the count. + /// + public int Count + { + get + { + return count; + } + + } + /// + /// Gets the data codewords. + /// + public int DataCodewords + { + get + { + return dataCodewords; + } + + } + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override String ToString() + { + return Convert.ToString(versionNumber); + } + + /// See ISO 18004:2006 6.5.1 Table 9 + 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))), + new Version(16, new int[] {6, 26, 50, 74}, + new ECBlocks(24, new ECB(5, 98), + new ECB(1, 99)), + new ECBlocks(28, new ECB(7, 45), + new ECB(3, 46)), + new ECBlocks(24, new ECB(15, 19), + new ECB(2, 20)), + new ECBlocks(30, new ECB(3, 15), + new ECB(13, 16))), + new Version(17, new int[] {6, 30, 54, 78}, + new ECBlocks(28, new ECB(1, 107), + new ECB(5, 108)), + new ECBlocks(28, new ECB(10, 46), + new ECB(1, 47)), + new ECBlocks(28, new ECB(1, 22), + new ECB(15, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(17, 15))), + new Version(18, new int[] {6, 30, 56, 82}, + new ECBlocks(30, new ECB(5, 120), + new ECB(1, 121)), + new ECBlocks(26, new ECB(9, 43), + new ECB(4, 44)), + new ECBlocks(28, new ECB(17, 22), + new ECB(1, 23)), + new ECBlocks(28, new ECB(2, 14), + new ECB(19, 15))), + new Version(19, new int[] {6, 30, 58, 86}, + new ECBlocks(28, new ECB(3, 113), + new ECB(4, 114)), + new ECBlocks(26, new ECB(3, 44), + new ECB(11, 45)), + new ECBlocks(26, new ECB(17, 21), + new ECB(4, 22)), + new ECBlocks(26, new ECB(9, 13), + new ECB(16, 14))), + new Version(20, new int[] {6, 34, 62, 90}, + new ECBlocks(28, new ECB(3, 107), + new ECB(5, 108)), + new ECBlocks(26, new ECB(3, 41), + new ECB(13, 42)), + new ECBlocks(30, new ECB(15, 24), + new ECB(5, 25)), + new ECBlocks(28, new ECB(15, 15), + new ECB(10, 16))), + new Version(21, new int[] {6, 28, 50, 72, 94}, + new ECBlocks(28, new ECB(4, 116), + new ECB(4, 117)), + new ECBlocks(26, new ECB(17, 42)), + new ECBlocks(28, new ECB(17, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(19, 16), + new ECB(6, 17))), + new Version(22, new int[] {6, 26, 50, 74, 98}, + new ECBlocks(28, new ECB(2, 111), + new ECB(7, 112)), + new ECBlocks(28, new ECB(17, 46)), + new ECBlocks(30, new ECB(7, 24), + new ECB(16, 25)), + new ECBlocks(24, new ECB(34, 13))), + new Version(23, new int[] {6, 30, 54, 78, 102}, + new ECBlocks(30, new ECB(4, 121), + new ECB(5, 122)), + new ECBlocks(28, new ECB(4, 47), + new ECB(14, 48)), + new ECBlocks(30, new ECB(11, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(16, 15), + new ECB(14, 16))), + new Version(24, new int[] {6, 28, 54, 80, 106}, + new ECBlocks(30, new ECB(6, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(6, 45), + new ECB(14, 46)), + new ECBlocks(30, new ECB(11, 24), + new ECB(16, 25)), + new ECBlocks(30, new ECB(30, 16), + new ECB(2, 17))), + new Version(25, new int[] {6, 32, 58, 84, 110}, + new ECBlocks(26, new ECB(8, 106), + new ECB(4, 107)), + new ECBlocks(28, new ECB(8, 47), + new ECB(13, 48)), + new ECBlocks(30, new ECB(7, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(13, 16))), + new Version(26, new int[] {6, 30, 58, 86, 114}, + new ECBlocks(28, new ECB(10, 114), + new ECB(2, 115)), + new ECBlocks(28, new ECB(19, 46), + new ECB(4, 47)), + new ECBlocks(28, new ECB(28, 22), + new ECB(6, 23)), + new ECBlocks(30, new ECB(33, 16), + new ECB(4, 17))), + new Version(27, new int[] {6, 34, 62, 90, 118}, + new ECBlocks(30, new ECB(8, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(22, 45), + new ECB(3, 46)), + new ECBlocks(30, new ECB(8, 23), + new ECB(26, 24)), + new ECBlocks(30, new ECB(12, 15), + new ECB(28, 16))), + new Version(28, new int[] {6, 26, 50, 74, 98, 122}, + new ECBlocks(30, new ECB(3, 117), + new ECB(10, 118)), + new ECBlocks(28, new ECB(3, 45), + new ECB(23, 46)), + new ECBlocks(30, new ECB(4, 24), + new ECB(31, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(31, 16))), + new Version(29, new int[] {6, 30, 54, 78, 102, 126}, + new ECBlocks(30, new ECB(7, 116), + new ECB(7, 117)), + new ECBlocks(28, new ECB(21, 45), + new ECB(7, 46)), + new ECBlocks(30, new ECB(1, 23), + new ECB(37, 24)), + new ECBlocks(30, new ECB(19, 15), + new ECB(26, 16))), + new Version(30, new int[] {6, 26, 52, 78, 104, 130}, + new ECBlocks(30, new ECB(5, 115), + new ECB(10, 116)), + new ECBlocks(28, new ECB(19, 47), + new ECB(10, 48)), + new ECBlocks(30, new ECB(15, 24), + new ECB(25, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(25, 16))), + new Version(31, new int[] {6, 30, 56, 82, 108, 134}, + new ECBlocks(30, new ECB(13, 115), + new ECB(3, 116)), + new ECBlocks(28, new ECB(2, 46), + new ECB(29, 47)), + new ECBlocks(30, new ECB(42, 24), + new ECB(1, 25)), + new ECBlocks(30, new ECB(23, 15), + new ECB(28, 16))), + new Version(32, new int[] {6, 34, 60, 86, 112, 138}, + new ECBlocks(30, new ECB(17, 115)), + new ECBlocks(28, new ECB(10, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(10, 24), + new ECB(35, 25)), + new ECBlocks(30, new ECB(19, 15), + new ECB(35, 16))), + new Version(33, new int[] {6, 30, 58, 86, 114, 142}, + new ECBlocks(30, new ECB(17, 115), + new ECB(1, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(21, 47)), + new ECBlocks(30, new ECB(29, 24), + new ECB(19, 25)), + new ECBlocks(30, new ECB(11, 15), + new ECB(46, 16))), + new Version(34, new int[] {6, 34, 62, 90, 118, 146}, + new ECBlocks(30, new ECB(13, 115), + new ECB(6, 116)), + new ECBlocks(28, new ECB(14, 46), + new ECB(23, 47)), + new ECBlocks(30, new ECB(44, 24), + new ECB(7, 25)), + new ECBlocks(30, new ECB(59, 16), + new ECB(1, 17))), + new Version(35, new int[] {6, 30, 54, 78, 102, 126, 150}, + new ECBlocks(30, new ECB(12, 121), + new ECB(7, 122)), + new ECBlocks(28, new ECB(12, 47), + new ECB(26, 48)), + new ECBlocks(30, new ECB(39, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(22, 15), + new ECB(41, 16))), + new Version(36, new int[] {6, 24, 50, 76, 102, 128, 154}, + new ECBlocks(30, new ECB(6, 121), + new ECB(14, 122)), + new ECBlocks(28, new ECB(6, 47), + new ECB(34, 48)), + new ECBlocks(30, new ECB(46, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(2, 15), + new ECB(64, 16))), + new Version(37, new int[] {6, 28, 54, 80, 106, 132, 158}, + new ECBlocks(30, new ECB(17, 122), + new ECB(4, 123)), + new ECBlocks(28, new ECB(29, 46), + new ECB(14, 47)), + new ECBlocks(30, new ECB(49, 24), + new ECB(10, 25)), + new ECBlocks(30, new ECB(24, 15), + new ECB(46, 16))), + new Version(38, new int[] {6, 32, 58, 84, 110, 136, 162}, + new ECBlocks(30, new ECB(4, 122), + new ECB(18, 123)), + new ECBlocks(28, new ECB(13, 46), + new ECB(32, 47)), + new ECBlocks(30, new ECB(48, 24), + new ECB(14, 25)), + new ECBlocks(30, new ECB(42, 15), + new ECB(32, 16))), + new Version(39, new int[] {6, 26, 54, 82, 110, 138, 166}, + new ECBlocks(30, new ECB(20, 117), + new ECB(4, 118)), + new ECBlocks(28, new ECB(40, 47), + new ECB(7, 48)), + new ECBlocks(30, new ECB(43, 24), + new ECB(22, 25)), + new ECBlocks(30, new ECB(10, 15), + new ECB(67, 16))), + new Version(40, new int[] {6, 30, 58, 86, 114, 142, 170}, + new ECBlocks(30, new ECB(19, 118), + new ECB(6, 119)), + new ECBlocks(28, new ECB(18, 47), + new ECB(31, 48)), + new ECBlocks(30, new ECB(34, 24), + new ECB(34, 25)), + new ECBlocks(30, new ECB(20, 15), + new ECB(61, 16))) + }; + } + } +} \ No newline at end of file diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 3cde5f63..27a3ab92 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -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.Height * 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.Height; 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); } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 1444ca66..ccbf8cc2 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -69,8 +69,23 @@ - + + + + + + + + + + + + + + + + From 42f976cdc628a3d705f1f010c8ae4b878119a886 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 24 Dec 2014 09:18:59 +0800 Subject: [PATCH 02/32] clean zxing --- shadowsocks-csharp/3rd/zxing/BitArray.cs | 328 ---------------- shadowsocks-csharp/3rd/zxing/BitMatrix.cs | 435 ---------------------- shadowsocks-csharp/3rd/zxing/EncodeHintType.cs | 131 ------- shadowsocks-csharp/3rd/zxing/Encoder.cs | 242 +----------- shadowsocks-csharp/3rd/zxing/FormatInformation.cs | 197 ---------- shadowsocks-csharp/3rd/zxing/GenericGF.cs | 40 -- shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs | 101 ----- shadowsocks-csharp/3rd/zxing/QRCode.cs | 34 -- shadowsocks-csharp/3rd/zxing/Version.cs | 345 +---------------- shadowsocks-csharp/View/QRCodeForm.cs | 4 +- shadowsocks-csharp/shadowsocks-csharp.csproj | 4 +- 11 files changed, 7 insertions(+), 1854 deletions(-) delete mode 100755 shadowsocks-csharp/3rd/zxing/BitMatrix.cs delete mode 100755 shadowsocks-csharp/3rd/zxing/EncodeHintType.cs delete mode 100755 shadowsocks-csharp/3rd/zxing/FormatInformation.cs diff --git a/shadowsocks-csharp/3rd/zxing/BitArray.cs b/shadowsocks-csharp/3rd/zxing/BitArray.cs index e0234e1a..b41484ca 100755 --- a/shadowsocks-csharp/3rd/zxing/BitArray.cs +++ b/shadowsocks-csharp/3rd/zxing/BitArray.cs @@ -49,11 +49,6 @@ namespace ZXing.Common { return (bits[i >> 5] & (1 << (i & 0x1F))) != 0; } - set - { - if (value) - bits[i >> 5] |= 1 << (i & 0x1F); - } } public BitArray() @@ -62,22 +57,6 @@ namespace ZXing.Common this.bits = new int[1]; } - public BitArray(int size) - { - if (size < 1) - { - throw new ArgumentException("size must be at least 1"); - } - this.size = size; - this.bits = makeArray(size); - } - - // For testing only - private BitArray(int[] bits, int size) - { - this.bits = bits; - this.size = size; - } private void ensureCapacity(int size) { @@ -89,200 +68,6 @@ namespace ZXing.Common } } - /// Flips bit i. - /// - /// - /// bit to set - /// - public void flip(int i) - { - bits[i >> 5] ^= 1 << (i & 0x1F); - } - - private static int numberOfTrailingZeros(int num) - { - var index = (-num & num)%37; - if (index < 0) - index *= -1; - return _lookup[index]; - } - - private static readonly int[] _lookup = - { - 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, 4, 7, 17, - 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, 5, 20, 8, 19, 18 - }; - - /// - /// Gets the next set. - /// - /// first bit to check - /// index of first bit that is set, starting from the given index, or size if none are set - /// at or beyond this given index - public int getNextSet(int from) - { - if (from >= size) - { - return size; - } - int bitsOffset = from >> 5; - int currentBits = bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) - { - if (++bitsOffset == bits.Length) - { - return size; - } - currentBits = bits[bitsOffset]; - } - int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /// - /// see getNextSet(int) - /// - /// index to start looking for unset bit - /// index of next unset bit, or if none are unset until the end - public int getNextUnset(int from) - { - if (from >= size) - { - return size; - } - int bitsOffset = from >> 5; - int currentBits = ~bits[bitsOffset]; - // mask off lesser bits first - currentBits &= ~((1 << (from & 0x1F)) - 1); - while (currentBits == 0) - { - if (++bitsOffset == bits.Length) - { - return size; - } - currentBits = ~bits[bitsOffset]; - } - int result = (bitsOffset << 5) + numberOfTrailingZeros(currentBits); - return result > size ? size : result; - } - - /// Sets a block of 32 bits, starting at bit i. - /// - /// - /// first bit to set - /// - /// the new value of the next 32 bits. Note again that the least-significant bit - /// corresponds to bit i, the next-least-significant to i+1, and so on. - /// - public void setBulk(int i, int newBits) - { - bits[i >> 5] = newBits; - } - - /// - /// Sets a range of bits. - /// - /// start of range, inclusive. - /// end of range, exclusive - public void setRange(int start, int end) - { - if (end < start) - { - throw new ArgumentException(); - } - if (end == start) - { - return; - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start >> 5; - int lastInt = end >> 5; - for (int i = firstInt; i <= lastInt; i++) - { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) - { - mask = -1; - } - else - { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) - { - mask |= 1 << j; - } - } - bits[i] |= mask; - } - } - - /// Clears all bits (sets to false). - public void clear() - { - int max = bits.Length; - for (int i = 0; i < max; i++) - { - bits[i] = 0; - } - } - - /// Efficient method to check if a range of bits is set, or not set. - /// - /// - /// start of range, inclusive. - /// - /// end of range, exclusive - /// - /// if true, checks that bits in range are set, otherwise checks that they are not set - /// - /// true iff all bits are set or not set in range, according to value argument - /// - /// IllegalArgumentException if end is less than or equal to start - public bool isRange(int start, int end, bool value) - { - if (end < start) - { - throw new System.ArgumentException(); - } - if (end == start) - { - return true; // empty range matches - } - end--; // will be easier to treat this as the last actually set bit -- inclusive - int firstInt = start >> 5; - int lastInt = end >> 5; - for (int i = firstInt; i <= lastInt; i++) - { - int firstBit = i > firstInt ? 0 : start & 0x1F; - int lastBit = i < lastInt ? 31 : end & 0x1F; - int mask; - if (firstBit == 0 && lastBit == 31) - { - mask = -1; - } - else - { - mask = 0; - for (int j = firstBit; j <= lastBit; j++) - { - mask |= 1 << j; - } - } - - // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is, - // equals the mask, or we're looking for 0s and the masked portion is not all 0s - if ((bits[i] & mask) != (value ? mask : 0)) - { - return false; - } - } - return true; - } - /// /// Appends the bit. /// @@ -297,14 +82,6 @@ namespace ZXing.Common size++; } - /// underlying array of ints. The first element holds the first 32 bits, and the least - /// significant bit is bit 0. - /// - public int[] Array - { - get { return bits; } - } - /// /// 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 @@ -374,115 +151,10 @@ namespace ZXing.Common } } - /// Reverses all bits in the array. - public void reverse() - { - var newBits = new int[bits.Length]; - // reverse all int's first - var len = ((size - 1) >> 5); - var oldBitsLen = len + 1; - for (var i = 0; i < oldBitsLen; i++) - { - var x = (long)bits[i]; - x = ((x >> 1) & 0x55555555u) | ((x & 0x55555555u) << 1); - x = ((x >> 2) & 0x33333333u) | ((x & 0x33333333u) << 2); - x = ((x >> 4) & 0x0f0f0f0fu) | ((x & 0x0f0f0f0fu) << 4); - x = ((x >> 8) & 0x00ff00ffu) | ((x & 0x00ff00ffu) << 8); - x = ((x >> 16) & 0x0000ffffu) | ((x & 0x0000ffffu) << 16); - newBits[len - i] = (int)x; - } - // now correct the int's if the bit size isn't a multiple of 32 - if (size != oldBitsLen * 32) - { - var leftOffset = oldBitsLen * 32 - size; - var mask = 1; - for (var i = 0; i < 31 - leftOffset; i++) - mask = (mask << 1) | 1; - var currentInt = (newBits[0] >> leftOffset) & mask; - for (var i = 1; i < oldBitsLen; i++) - { - var nextInt = newBits[i]; - currentInt |= nextInt << (32 - leftOffset); - newBits[i - 1] = currentInt; - currentInt = (nextInt >> leftOffset) & mask; - } - newBits[oldBitsLen - 1] = currentInt; - } - bits = newBits; - } - private static int[] makeArray(int size) { return new int[(size + 31) >> 5]; } - /// - /// Determines whether the specified is equal to this instance. - /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// - public override bool Equals(Object o) - { - var other = o as BitArray; - if (other == null) - return false; - if (size != other.size) - return false; - for (var index = 0; index < size; index++) - { - if (bits[index] != other.bits[index]) - return false; - } - return true; - } - - /// - /// Returns a hash code for this instance. - /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// - public override int GetHashCode() - { - var hash = size; - foreach (var bit in bits) - { - hash = 31 * hash + bit.GetHashCode(); - } - return hash; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - var result = new System.Text.StringBuilder(size); - for (int i = 0; i < size; i++) - { - if ((i & 0x07) == 0) - { - result.Append(' '); - } - result.Append(this[i] ? 'X' : '.'); - } - return result.ToString(); - } - - /// - /// Erstellt ein neues Objekt, das eine Kopie der aktuellen Instanz darstellt. - /// - /// - /// Ein neues Objekt, das eine Kopie dieser Instanz darstellt. - /// - public object Clone() - { - return new BitArray((int[])bits.Clone(), size); - } } } \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/BitMatrix.cs b/shadowsocks-csharp/3rd/zxing/BitMatrix.cs deleted file mode 100755 index d0378d45..00000000 --- a/shadowsocks-csharp/3rd/zxing/BitMatrix.cs +++ /dev/null @@ -1,435 +0,0 @@ -/* -* 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 -{ - /// - ///

Represents a 2D matrix of bits. In function arguments below, and throughout the common - /// module, x is the column position, and y is the row position. The ordering is always x, y. - /// The origin is at the top-left.

- ///

Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins - /// with a new int. This is done intentionally so that we can copy out a row into a BitArray very - /// efficiently.

- ///

The ordering of bits is row-major. Within each int, the least significant bits are used first, - /// meaning they represent lower x values. This is compatible with BitArray's implementation.

- ///
- /// Sean Owen - /// dswitkin@google.com (Daniel Switkin) - public sealed partial class BitMatrix - { - private readonly int width; - private readonly int height; - private readonly int rowSize; - private readonly int[] bits; - - /// The width of the matrix - /// - public int Width - { - get - { - return width; - } - - } - /// The height of the matrix - /// - public int Height - { - get - { - return height; - } - - } - /// This method is for compatibility with older code. It's only logical to call if the matrix - /// is square, so I'm throwing if that's not the case. - /// - /// - /// row/column dimension of this matrix - /// - public int Dimension - { - get - { - if (width != height) - { - throw new System.ArgumentException("Can't call getDimension() on a non-square matrix"); - } - return width; - } - - } - - // A helper to construct a square matrix. - public BitMatrix(int dimension) - : this(dimension, dimension) - { - } - - public BitMatrix(int width, int height) - { - if (width < 1 || height < 1) - { - throw new System.ArgumentException("Both dimensions must be greater than 0"); - } - this.width = width; - this.height = height; - this.rowSize = (width + 31) >> 5; - bits = new int[rowSize * height]; - } - - internal BitMatrix(int width, int height, int rowSize, int[] bits) - { - this.width = width; - this.height = height; - this.rowSize = rowSize; - this.bits = bits; - } - - internal BitMatrix(int width, int height, int[] bits) - { - this.width = width; - this.height = height; - this.rowSize = (width + 31) >> 5; - this.bits = bits; - } - - ///

Gets the requested bit, where true means black.

- /// - ///
- /// The horizontal component (i.e. which column) - /// - /// The vertical component (i.e. which row) - /// - /// value of given bit in matrix - /// - public bool this[int x, int y] - { - get - { - int offset = y * rowSize + (x >> 5); - return (((int)((uint)(bits[offset]) >> (x & 0x1f))) & 1) != 0; - } - set - { - if (value) - { - int offset = y * rowSize + (x >> 5); - bits[offset] |= 1 << (x & 0x1f); - } - } - } - - ///

Flips the given bit.

- /// - ///
- /// The horizontal component (i.e. which column) - /// - /// The vertical component (i.e. which row) - /// - public void flip(int x, int y) - { - int offset = y * rowSize + (x >> 5); - bits[offset] ^= 1 << (x & 0x1f); - } - - /// Clears all bits (sets to false). - public void clear() - { - int max = bits.Length; - for (int i = 0; i < max; i++) - { - bits[i] = 0; - } - } - - ///

Sets a square region of the bit matrix to true.

- /// - ///
- /// The horizontal position to begin at (inclusive) - /// - /// The vertical position to begin at (inclusive) - /// - /// The width of the region - /// - /// The height of the region - /// - public void setRegion(int left, int top, int width, int height) - { - if (top < 0 || left < 0) - { - throw new System.ArgumentException("Left and top must be nonnegative"); - } - if (height < 1 || width < 1) - { - throw new System.ArgumentException("Height and width must be at least 1"); - } - int right = left + width; - int bottom = top + height; - if (bottom > this.height || right > this.width) - { - throw new System.ArgumentException("The region must fit inside the matrix"); - } - for (int y = top; y < bottom; y++) - { - int offset = y * rowSize; - for (int x = left; x < right; x++) - { - bits[offset + (x >> 5)] |= 1 << (x & 0x1f); - } - } - } - - /// A fast method to retrieve one row of data from the matrix as a BitArray. - /// - /// - /// The row to retrieve - /// - /// An optional caller-allocated BitArray, will be allocated if null or too small - /// - /// The resulting BitArray - this reference should always be used even when passing - /// your own row - /// - public BitArray getRow(int y, BitArray row) - { - if (row == null || row.Size < width) - { - row = new BitArray(width); - } - else - { - row.clear(); - } - int offset = y * rowSize; - for (int x = 0; x < rowSize; x++) - { - row.setBulk(x << 5, bits[offset + x]); - } - return row; - } - - /// - /// Sets the row. - /// - /// row to set - /// {@link BitArray} to copy from - public void setRow(int y, BitArray row) - { - Array.Copy(row.Array, 0, bits, y * rowSize, rowSize); - } - - /// - /// Modifies this {@code BitMatrix} to represent the same but rotated 180 degrees - /// - public void rotate180() - { - var width = Width; - var height = Height; - var topRow = new BitArray(width); - var bottomRow = new BitArray(width); - for (int i = 0; i < (height + 1)/2; i++) - { - topRow = getRow(i, topRow); - bottomRow = getRow(height - 1 - i, bottomRow); - topRow.reverse(); - bottomRow.reverse(); - setRow(i, bottomRow); - setRow(height - 1 - i, topRow); - } - } - - /// - /// This is useful in detecting the enclosing rectangle of a 'pure' barcode. - /// - /// {left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white - public int[] getEnclosingRectangle() - { - int left = width; - int top = height; - int right = -1; - int bottom = -1; - - for (int y = 0; y < height; y++) - { - for (int x32 = 0; x32 < rowSize; x32++) - { - int theBits = bits[y * rowSize + x32]; - if (theBits != 0) - { - if (y < top) - { - top = y; - } - if (y > bottom) - { - bottom = y; - } - if (x32 * 32 < left) - { - int bit = 0; - while ((theBits << (31 - bit)) == 0) - { - bit++; - } - if ((x32 * 32 + bit) < left) - { - left = x32 * 32 + bit; - } - } - if (x32 * 32 + 31 > right) - { - int bit = 31; - while (((int)((uint)theBits >> bit)) == 0) // (theBits >>> bit) - { - bit--; - } - if ((x32 * 32 + bit) > right) - { - right = x32 * 32 + bit; - } - } - } - } - } - - int widthTmp = right - left; - int heightTmp = bottom - top; - - if (widthTmp < 0 || heightTmp < 0) - { - return null; - } - - return new [] { left, top, widthTmp, heightTmp }; - } - - /// - /// This is useful in detecting a corner of a 'pure' barcode. - /// - /// {x,y} coordinate of top-left-most 1 bit, or null if it is all white - public int[] getTopLeftOnBit() - { - int bitsOffset = 0; - while (bitsOffset < bits.Length && bits[bitsOffset] == 0) - { - bitsOffset++; - } - if (bitsOffset == bits.Length) - { - return null; - } - int y = bitsOffset / rowSize; - int x = (bitsOffset % rowSize) << 5; - - int theBits = bits[bitsOffset]; - int bit = 0; - while ((theBits << (31 - bit)) == 0) - { - bit++; - } - x += bit; - return new[] { x, y }; - } - - public int[] getBottomRightOnBit() - { - int bitsOffset = bits.Length - 1; - while (bitsOffset >= 0 && bits[bitsOffset] == 0) - { - bitsOffset--; - } - if (bitsOffset < 0) - { - return null; - } - - int y = bitsOffset / rowSize; - int x = (bitsOffset % rowSize) << 5; - - int theBits = bits[bitsOffset]; - int bit = 31; - - while (((int)((uint)theBits >> bit)) == 0) // (theBits >>> bit) - { - bit--; - } - x += bit; - - return new int[] { x, y }; - } - - public override bool Equals(object obj) - { - if (!(obj is BitMatrix)) - { - return false; - } - BitMatrix other = (BitMatrix)obj; - if (width != other.width || height != other.height || - rowSize != other.rowSize || bits.Length != other.bits.Length) - { - return false; - } - for (int i = 0; i < bits.Length; i++) - { - if (bits[i] != other.bits[i]) - { - return false; - } - } - return true; - } - - public override int GetHashCode() - { - int hash = width; - hash = 31 * hash + width; - hash = 31 * hash + height; - hash = 31 * hash + rowSize; - foreach (var bit in bits) - { - hash = 31 * hash + bit.GetHashCode(); - } - return hash; - } - - public override String ToString() - { - var result = new System.Text.StringBuilder(height * (width + 1)); - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) - { - result.Append(this[x, y] ? "X " : " "); - } -#if WindowsCE - result.Append("\r\n"); -#else - result.AppendLine(""); -#endif - } - return result.ToString(); - } - - public object Clone() - { - return new BitMatrix(width, height, rowSize, (int[])bits.Clone()); - } - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs b/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs deleted file mode 100755 index 01b17f8c..00000000 --- a/shadowsocks-csharp/3rd/zxing/EncodeHintType.cs +++ /dev/null @@ -1,131 +0,0 @@ -/* -* 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 -{ - /// - /// These are a set of hints that you may pass to Writers to specify their behavior. - /// - /// dswitkin@google.com (Daniel Switkin) - public enum EncodeHintType - { - /// - /// Specifies the width of the barcode image - /// type: - /// - WIDTH, - - /// - /// Specifies the height of the barcode image - /// type: - /// - HEIGHT, - - /// - /// Don't put the content string into the output image. - /// type: - /// - PURE_BARCODE, - - /// - /// Specifies what degree of error correction to use, for example in QR Codes. - /// Type depends on the encoder. For example for QR codes it's type - /// - /// For Aztec it is of type , representing the minimal percentage of error correction words. - /// Note: an Aztec symbol should have a minimum of 25% EC words. - /// For PDF417 it is of type or (between 0 and 8), - /// - ERROR_CORRECTION, - - /// - /// Specifies what character encoding to use where applicable. - /// type: - /// - CHARACTER_SET, - - /// - /// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary - /// by format; for example it controls margin before and after the barcode horizontally for - /// most 1D formats. - /// type: - /// - MARGIN, - - /// - /// Specifies whether to use compact mode for PDF417. - /// type: - /// - PDF417_COMPACT, - - /// - /// Specifies what compaction mode to use for PDF417. - /// type: - /// - PDF417_COMPACTION, - - /// - /// Specifies the minimum and maximum number of rows and columns for PDF417. - /// type: - /// - PDF417_DIMENSIONS, - - /// - /// Don't append ECI segment. - /// That is against the specification of QR Code but some - /// readers have problems if the charset is switched from - /// ISO-8859-1 (default) to UTF-8 with the necessary ECI segment. - /// If you set the property to true you can use UTF-8 encoding - /// and the ECI segment is omitted. - /// type: - /// - DISABLE_ECI, - - /// - /// Specifies the matrix shape for Data Matrix (type ) - /// - DATA_MATRIX_SHAPE, - - /// - /// Specifies a minimum barcode size (type ). Only applicable to Data Matrix now. - /// - MIN_SIZE, - - /// - /// Specifies a maximum barcode size (type ). Only applicable to Data Matrix now. - /// - MAX_SIZE, - - /// - /// if true, don't switch to codeset C for numbers - /// - CODE128_FORCE_CODESET_B, - - /// - /// Specifies the default encodation for Data Matrix (type ) - /// Make sure that the content fits into the encodation value, otherwise there will be an exception thrown. - /// standard value: Encodation.ASCII - /// - DATA_MATRIX_DEFAULT_ENCODATION, - - /// - /// Specifies the required number of layers for an Aztec code: - /// a negative number (-1, -2, -3, -4) specifies a compact Aztec code - /// 0 indicates to use the minimum number of layers (the default) - /// a positive number (1, 2, .. 32) specifies a normal (non-compact) Aztec code - /// - AZTEC_LAYERS, - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/Encoder.cs b/shadowsocks-csharp/3rd/zxing/Encoder.cs index 694d6ca4..ae9996e9 100755 --- a/shadowsocks-csharp/3rd/zxing/Encoder.cs +++ b/shadowsocks-csharp/3rd/zxing/Encoder.cs @@ -30,15 +30,6 @@ namespace ZXing.QrCode.Internal public static class Encoder { - // The original table is defined in the table 5 of JISX0510:2004 (p.19). - private static readonly int[] ALPHANUMERIC_TABLE = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f - 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f - -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f - }; internal static String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1"; @@ -66,28 +57,10 @@ namespace ZXing.QrCode.Internal /// representing the encoded QR code public static QRCode encode(String content, ErrorCorrectionLevel ecLevel) { - return encode(content, ecLevel, null); - } - - /// - /// Encodes the specified content. - /// - /// The content. - /// The ec level. - /// The hints. - /// - public static QRCode encode(String content, - ErrorCorrectionLevel ecLevel, - IDictionary hints) - { // Determine what character encoding has been specified by the caller, if any #if !SILVERLIGHT || WINDOWS_PHONE - String encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; - if (encoding == null) - { - encoding = DEFAULT_BYTE_MODE_ENCODING; - } - bool generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding); + 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"; @@ -98,7 +71,7 @@ namespace ZXing.QrCode.Internal // 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 = chooseMode(content, encoding); + Mode mode = Mode.BYTE; // This will store the header information, like mode and // length, as well as "header" segments like an ECI segment. @@ -183,106 +156,6 @@ namespace ZXing.QrCode.Internal return qrCode; } - /// - /// Gets the alphanumeric code. - /// - /// The code. - /// the code point of the table used in alphanumeric mode or - /// -1 if there is no corresponding code in the table. - internal static int getAlphanumericCode(int code) - { - if (code < ALPHANUMERIC_TABLE.Length) - { - return ALPHANUMERIC_TABLE[code]; - } - return -1; - } - - /// - /// Chooses the mode. - /// - /// The content. - /// - public static Mode chooseMode(String content) - { - return chooseMode(content, null); - } - - /// - /// Choose the best mode by examining the content. Note that 'encoding' is used as a hint; - /// if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}. - /// - /// The content. - /// The encoding. - /// - private static Mode chooseMode(String content, String encoding) - { - if ("Shift_JIS".Equals(encoding)) - { - - // Choose Kanji mode if all input are double-byte characters - return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE; - } - bool hasNumeric = false; - bool hasAlphanumeric = false; - for (int i = 0; i < content.Length; ++i) - { - char c = content[i]; - if (c >= '0' && c <= '9') - { - hasNumeric = true; - } - else if (getAlphanumericCode(c) != -1) - { - hasAlphanumeric = true; - } - else - { - return Mode.BYTE; - } - } - if (hasAlphanumeric) - { - - return Mode.ALPHANUMERIC; - } - if (hasNumeric) - { - - return Mode.NUMERIC; - } - return Mode.BYTE; - } - - private static bool isOnlyDoubleByteKanji(String content) - { - byte[] bytes; - try - { - bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); - } - catch (Exception ) - { - return false; - } - int length = bytes.Length; - if (length % 2 != 0) - { - return false; - } - for (int i = 0; i < length; i += 2) - { - - - int byte1 = bytes[i] & 0xFF; - if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) - { - - return false; - } - } - return true; - } private static int chooseMaskPattern(BitArray bits, ErrorCorrectionLevel ecLevel, @@ -594,85 +467,12 @@ namespace ZXing.QrCode.Internal BitArray bits, String encoding) { - if (mode.Equals(Mode.NUMERIC)) - appendNumericBytes(content, bits); - else - if (mode.Equals(Mode.ALPHANUMERIC)) - appendAlphanumericBytes(content, bits); - else if (mode.Equals(Mode.BYTE)) append8BitBytes(content, bits, encoding); - else - if (mode.Equals(Mode.KANJI)) - appendKanjiBytes(content, bits); else throw new Exception("Invalid mode: " + mode); } - internal static void appendNumericBytes(String content, BitArray bits) - { - int length = content.Length; - - int i = 0; - while (i < length) - { - int num1 = content[i] - '0'; - if (i + 2 < length) - { - // Encode three numeric letters in ten bits. - int num2 = content[i + 1] - '0'; - int num3 = content[i + 2] - '0'; - bits.appendBits(num1 * 100 + num2 * 10 + num3, 10); - i += 3; - } - else if (i + 1 < length) - { - // Encode two numeric letters in seven bits. - int num2 = content[i + 1] - '0'; - bits.appendBits(num1 * 10 + num2, 7); - i += 2; - } - else - { - // Encode one numeric letter in four bits. - bits.appendBits(num1, 4); - i++; - } - } - } - - internal static void appendAlphanumericBytes(String content, BitArray bits) - { - int length = content.Length; - - int i = 0; - while (i < length) - { - int code1 = getAlphanumericCode(content[i]); - if (code1 == -1) - { - throw new Exception(); - } - if (i + 1 < length) - { - int code2 = getAlphanumericCode(content[i + 1]); - if (code2 == -1) - { - throw new Exception(); - } - // Encode two alphanumeric letters in 11 bits. - bits.appendBits(code1 * 45 + code2, 11); - i += 2; - } - else - { - // Encode one alphanumeric letter in six bits. - bits.appendBits(code1, 6); - i++; - } - } - } - internal static void append8BitBytes(String content, BitArray bits, String encoding) { byte[] bytes; @@ -712,42 +512,6 @@ namespace ZXing.QrCode.Internal } } - internal static void appendKanjiBytes(String content, BitArray bits) - { - byte[] bytes; - try - { - bytes = Encoding.GetEncoding("Shift_JIS").GetBytes(content); - } - catch (Exception uee) - { - throw new Exception(uee.Message, uee); - } - int length = bytes.Length; - for (int i = 0; i < length; i += 2) - { - int byte1 = bytes[i] & 0xFF; - int byte2 = bytes[i + 1] & 0xFF; - int code = (byte1 << 8) | byte2; - int subtracted = -1; - if (code >= 0x8140 && code <= 0x9ffc) - { - - subtracted = code - 0x8140; - } - else if (code >= 0xe040 && code <= 0xebbf) - { - subtracted = code - 0xc140; - } - if (subtracted == -1) - { - - throw new Exception("Invalid byte sequence"); - } - int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff); - bits.appendBits(encoded, 13); - } - } /* private static void appendECI(CharacterSetECI eci, BitArray bits) diff --git a/shadowsocks-csharp/3rd/zxing/FormatInformation.cs b/shadowsocks-csharp/3rd/zxing/FormatInformation.cs deleted file mode 100755 index 88b5045e..00000000 --- a/shadowsocks-csharp/3rd/zxing/FormatInformation.cs +++ /dev/null @@ -1,197 +0,0 @@ -/* -* 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 -{ - - ///

Encapsulates a QR Code's format information, including the data mask used and - /// error correction level.

- /// - ///
- /// Sean Owen - /// - /// www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source - /// - /// - /// - /// - /// - sealed class FormatInformation - { - private const int FORMAT_INFO_MASK_QR = 0x5412; - - /// See ISO 18004:2006, Annex C, Table C.1 - private static readonly int[][] FORMAT_INFO_DECODE_LOOKUP = new int[][] - { - new [] { 0x5412, 0x00 }, - new [] { 0x5125, 0x01 }, - new [] { 0x5E7C, 0x02 }, - new [] { 0x5B4B, 0x03 }, - new [] { 0x45F9, 0x04 }, - new [] { 0x40CE, 0x05 }, - new [] { 0x4F97, 0x06 }, - new [] { 0x4AA0, 0x07 }, - new [] { 0x77C4, 0x08 }, - new [] { 0x72F3, 0x09 }, - new [] { 0x7DAA, 0x0A }, - new [] { 0x789D, 0x0B }, - new [] { 0x662F, 0x0C }, - new [] { 0x6318, 0x0D }, - new [] { 0x6C41, 0x0E }, - new [] { 0x6976, 0x0F }, - new [] { 0x1689, 0x10 }, - new [] { 0x13BE, 0x11 }, - new [] { 0x1CE7, 0x12 }, - new [] { 0x19D0, 0x13 }, - new [] { 0x0762, 0x14 }, - new [] { 0x0255, 0x15 }, - new [] { 0x0D0C, 0x16 }, - new [] { 0x083B, 0x17 }, - new [] { 0x355F, 0x18 }, - new [] { 0x3068, 0x19 }, - new [] { 0x3F31, 0x1A }, - new [] { 0x3A06, 0x1B }, - new [] { 0x24B4, 0x1C }, - new [] { 0x2183, 0x1D }, - new [] { 0x2EDA, 0x1E }, - new [] { 0x2BED, 0x1F } - }; - - /// Offset i holds the number of 1 bits in the binary representation of i - private static readonly int[] BITS_SET_IN_HALF_BYTE = new [] - { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 }; - - private readonly ErrorCorrectionLevel errorCorrectionLevel; - private readonly byte dataMask; - - private FormatInformation(int formatInfo) - { - // Bits 3,4 - errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); - // Bottom 3 bits - dataMask = (byte)(formatInfo & 0x07); - } - - internal static int numBitsDiffering(int a, int b) - { - a ^= b; // a now has a 1 bit exactly where its bit differs with b's - // Count bits set quickly with a series of lookups: - return BITS_SET_IN_HALF_BYTE[a & 0x0F] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 4)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 8)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 12)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 16)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 20)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 24)) & 0x0F)] + - BITS_SET_IN_HALF_BYTE[(((int)((uint)a >> 28)) & 0x0F)]; - } - - /// - /// Decodes the format information. - /// - /// format info indicator, with mask still applied - /// The masked format info2. - /// - /// information about the format it specifies, or null - /// if doesn't seem to match any known pattern - /// - internal static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) - { - FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2); - if (formatInfo != null) - { - return formatInfo; - } - // Should return null, but, some QR codes apparently - // do not mask this info. Try again by actually masking the pattern - // first - return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR, - maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR); - } - - private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) - { - // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing - int bestDifference = Int32.MaxValue; - int bestFormatInfo = 0; - foreach (var decodeInfo in FORMAT_INFO_DECODE_LOOKUP) - { - int targetInfo = decodeInfo[0]; - if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) - { - // Found an exact match - return new FormatInformation(decodeInfo[1]); - } - int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo); - if (bitsDifference < bestDifference) - { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - if (maskedFormatInfo1 != maskedFormatInfo2) - { - // also try the other option - bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo); - if (bitsDifference < bestDifference) - { - bestFormatInfo = decodeInfo[1]; - bestDifference = bitsDifference; - } - } - } - // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits - // differing means we found a match - if (bestDifference <= 3) - { - return new FormatInformation(bestFormatInfo); - } - return null; - } - - internal ErrorCorrectionLevel ErrorCorrectionLevel - { - get - { - return errorCorrectionLevel; - } - } - - internal byte DataMask - { - get - { - return dataMask; - } - } - - public override int GetHashCode() - { - return (errorCorrectionLevel.ordinal() << 3) | dataMask; - } - - public override bool Equals(Object o) - { - if (!(o is FormatInformation)) - { - return false; - } - var other = (FormatInformation)o; - return errorCorrectionLevel == other.errorCorrectionLevel && dataMask == other.dataMask; - } - } -} \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/GenericGF.cs b/shadowsocks-csharp/3rd/zxing/GenericGF.cs index 8a2835ea..d7b8d350 100755 --- a/shadowsocks-csharp/3rd/zxing/GenericGF.cs +++ b/shadowsocks-csharp/3rd/zxing/GenericGF.cs @@ -91,14 +91,6 @@ namespace ZXing.Common.ReedSolomon } } - internal GenericGFPoly One - { - get - { - return one; - } - } - /// /// Builds the monomial. /// @@ -138,19 +130,6 @@ namespace ZXing.Common.ReedSolomon return expTable[a]; } - /// - /// Logs the specified a. - /// - /// A. - /// base 2 log of a in GF(size) - internal int log(int a) - { - if (a == 0) - { - throw new ArgumentException(); - } - return logTable[a]; - } /// /// Inverses the specified a. @@ -181,30 +160,11 @@ namespace ZXing.Common.ReedSolomon } /// - /// Gets the size. - /// - public int Size - { - get { return size; } - } - - /// /// Gets the generator base. /// public int GeneratorBase { get { return generatorBase; } } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - override public String ToString() - { - return "GF(0x" + primitive.ToString("X") + ',' + size + ')'; - } } } \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs b/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs index 8307a1dd..eb966579 100755 --- a/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs +++ b/shadowsocks-csharp/3rd/zxing/GenericGFPoly.cs @@ -112,36 +112,6 @@ namespace ZXing.Common.ReedSolomon return coefficients[coefficients.Length - 1 - degree]; } - /// - /// evaluation of this polynomial at a given point - /// - /// A. - /// evaluation of this polynomial at a given point - internal int evaluateAt(int a) - { - int result = 0; - if (a == 0) - { - // Just return the x^0 coefficient - return getCoefficient(0); - } - int size = coefficients.Length; - if (a == 1) - { - // Just the sum of the coefficients - foreach (var coefficient in coefficients) - { - result = GenericGF.addOrSubtract(result, coefficient); - } - return result; - } - result = coefficients[0]; - for (int i = 1; i < size; i++) - { - result = GenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]); - } - return result; - } internal GenericGFPoly addOrSubtract(GenericGFPoly other) { @@ -206,24 +176,6 @@ namespace ZXing.Common.ReedSolomon return new GenericGFPoly(field, product); } - internal GenericGFPoly multiply(int scalar) - { - if (scalar == 0) - { - return field.Zero; - } - if (scalar == 1) - { - return this; - } - int size = coefficients.Length; - int[] product = new int[size]; - for (int i = 0; i < size; i++) - { - product[i] = field.multiply(coefficients[i], scalar); - } - return new GenericGFPoly(field, product); - } internal GenericGFPoly multiplyByMonomial(int degree, int coefficient) { @@ -274,58 +226,5 @@ namespace ZXing.Common.ReedSolomon return new GenericGFPoly[] { quotient, remainder }; } - public override String ToString() - { - StringBuilder result = new StringBuilder(8 * Degree); - for (int degree = Degree; degree >= 0; degree--) - { - int coefficient = getCoefficient(degree); - if (coefficient != 0) - { - if (coefficient < 0) - { - result.Append(" - "); - coefficient = -coefficient; - } - else - { - if (result.Length > 0) - { - result.Append(" + "); - } - } - if (degree == 0 || coefficient != 1) - { - int alphaPower = field.log(coefficient); - if (alphaPower == 0) - { - result.Append('1'); - } - else if (alphaPower == 1) - { - result.Append('a'); - } - else - { - result.Append("a^"); - result.Append(alphaPower); - } - } - if (degree != 0) - { - if (degree == 1) - { - result.Append('x'); - } - else - { - result.Append("x^"); - result.Append(degree); - } - } - } - } - return result.ToString(); - } } } \ No newline at end of file diff --git a/shadowsocks-csharp/3rd/zxing/QRCode.cs b/shadowsocks-csharp/3rd/zxing/QRCode.cs index 312f94ef..123d4f18 100755 --- a/shadowsocks-csharp/3rd/zxing/QRCode.cs +++ b/shadowsocks-csharp/3rd/zxing/QRCode.cs @@ -77,40 +77,6 @@ namespace ZXing.QrCode.Internal public ByteMatrix Matrix { get; set; } /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - var result = new StringBuilder(200); - result.Append("<<\n"); - result.Append(" mode: "); - result.Append(Mode); - result.Append("\n ecLevel: "); - result.Append(ECLevel); - result.Append("\n version: "); - if (Version == null) - result.Append("null"); - else - result.Append(Version); - result.Append("\n maskPattern: "); - result.Append(MaskPattern); - if (Matrix == null) - { - result.Append("\n matrix: null\n"); - } - else - { - result.Append("\n matrix:\n"); - result.Append(Matrix.ToString()); - } - result.Append(">>\n"); - return result.ToString(); - } - - /// /// Check if "mask_pattern" is valid. /// /// The mask pattern. diff --git a/shadowsocks-csharp/3rd/zxing/Version.cs b/shadowsocks-csharp/3rd/zxing/Version.cs index 1404a709..be531ca4 100755 --- a/shadowsocks-csharp/3rd/zxing/Version.cs +++ b/shadowsocks-csharp/3rd/zxing/Version.cs @@ -26,19 +26,6 @@ namespace ZXing.QrCode.Internal /// Sean Owen public sealed class Version { - /// See ISO 18004:2006 Annex D. - /// Element i represents the raw version bits that specify version i + 7 - /// - private static readonly int[] VERSION_DECODE_INFO = new[] - { - 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, - 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, - 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683, - 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB, - 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250, - 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B, - 0x2542E, 0x26A64, 0x27541, 0x28C69 - }; private static readonly Version[] VERSIONS = buildVersions(); @@ -75,18 +62,6 @@ namespace ZXing.QrCode.Internal } /// - /// Gets the alignment pattern centers. - /// - public int[] AlignmentPatternCenters - { - get - { - return alignmentPatternCenters; - } - - } - - /// /// Gets the total codewords. /// public int TotalCodewords @@ -120,28 +95,6 @@ namespace ZXing.QrCode.Internal return ecBlocks[ecLevel.ordinal()]; } - ///

Deduces version information purely from QR Code dimensions.

- /// - ///
- /// dimension in modules - /// - /// for a QR Code of that dimension or null - public static Version getProvisionalVersionForDimension(int dimension) - { - if (dimension % 4 != 1) - { - return null; - } - try - { - return getVersionForNumber((dimension - 17) >> 2); - } - catch (ArgumentException) - { - return null; - } - } - /// /// Gets the version for number. /// @@ -156,81 +109,6 @@ namespace ZXing.QrCode.Internal return VERSIONS[versionNumber - 1]; } - internal static Version decodeVersionInformation(int versionBits) - { - int bestDifference = Int32.MaxValue; - int bestVersion = 0; - for (int i = 0; i < VERSION_DECODE_INFO.Length; i++) - { - int targetVersion = VERSION_DECODE_INFO[i]; - // Do the version info bits match exactly? done. - if (targetVersion == versionBits) - { - return getVersionForNumber(i + 7); - } - // Otherwise see if this is the closest to a real version info bit string - // we have seen so far - int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion); - if (bitsDifference < bestDifference) - { - bestVersion = i + 7; - bestDifference = bitsDifference; - } - } - // We can tolerate up to 3 bits of error since no two version info codewords will - // differ in less than 8 bits. - if (bestDifference <= 3) - { - return getVersionForNumber(bestVersion); - } - // If we didn't find a close enough match, fail - return null; - } - - /// See ISO 18004:2006 Annex E - internal BitMatrix buildFunctionPattern() - { - int dimension = DimensionForVersion; - BitMatrix bitMatrix = new BitMatrix(dimension); - - // Top left finder pattern + separator + format - bitMatrix.setRegion(0, 0, 9, 9); - // Top right finder pattern + separator + format - bitMatrix.setRegion(dimension - 8, 0, 8, 9); - // Bottom left finder pattern + separator + format - bitMatrix.setRegion(0, dimension - 8, 9, 8); - - // Alignment patterns - int max = alignmentPatternCenters.Length; - for (int x = 0; x < max; x++) - { - int i = alignmentPatternCenters[x] - 2; - for (int y = 0; y < max; y++) - { - if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) - { - // No alignment patterns near the three finder paterns - continue; - } - bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5); - } - } - - // Vertical timing pattern - bitMatrix.setRegion(6, 9, 1, dimension - 17); - // Horizontal timing pattern - bitMatrix.setRegion(9, 6, dimension - 17, 1); - - if (versionNumber > 6) - { - // Version info, top right - bitMatrix.setRegion(dimension - 11, 0, 3, 6); - // Version info, bottom left - bitMatrix.setRegion(0, dimension - 11, 6, 3); - } - - return bitMatrix; - } ///

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 @@ -457,228 +335,7 @@ namespace ZXing.QrCode.Internal new ECBlocks(30, new ECB(5, 24), new ECB(7, 25)), new ECBlocks(24, new ECB(11, 12), - new ECB(7, 13))), - new Version(16, new int[] {6, 26, 50, 74}, - new ECBlocks(24, new ECB(5, 98), - new ECB(1, 99)), - new ECBlocks(28, new ECB(7, 45), - new ECB(3, 46)), - new ECBlocks(24, new ECB(15, 19), - new ECB(2, 20)), - new ECBlocks(30, new ECB(3, 15), - new ECB(13, 16))), - new Version(17, new int[] {6, 30, 54, 78}, - new ECBlocks(28, new ECB(1, 107), - new ECB(5, 108)), - new ECBlocks(28, new ECB(10, 46), - new ECB(1, 47)), - new ECBlocks(28, new ECB(1, 22), - new ECB(15, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(17, 15))), - new Version(18, new int[] {6, 30, 56, 82}, - new ECBlocks(30, new ECB(5, 120), - new ECB(1, 121)), - new ECBlocks(26, new ECB(9, 43), - new ECB(4, 44)), - new ECBlocks(28, new ECB(17, 22), - new ECB(1, 23)), - new ECBlocks(28, new ECB(2, 14), - new ECB(19, 15))), - new Version(19, new int[] {6, 30, 58, 86}, - new ECBlocks(28, new ECB(3, 113), - new ECB(4, 114)), - new ECBlocks(26, new ECB(3, 44), - new ECB(11, 45)), - new ECBlocks(26, new ECB(17, 21), - new ECB(4, 22)), - new ECBlocks(26, new ECB(9, 13), - new ECB(16, 14))), - new Version(20, new int[] {6, 34, 62, 90}, - new ECBlocks(28, new ECB(3, 107), - new ECB(5, 108)), - new ECBlocks(26, new ECB(3, 41), - new ECB(13, 42)), - new ECBlocks(30, new ECB(15, 24), - new ECB(5, 25)), - new ECBlocks(28, new ECB(15, 15), - new ECB(10, 16))), - new Version(21, new int[] {6, 28, 50, 72, 94}, - new ECBlocks(28, new ECB(4, 116), - new ECB(4, 117)), - new ECBlocks(26, new ECB(17, 42)), - new ECBlocks(28, new ECB(17, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(19, 16), - new ECB(6, 17))), - new Version(22, new int[] {6, 26, 50, 74, 98}, - new ECBlocks(28, new ECB(2, 111), - new ECB(7, 112)), - new ECBlocks(28, new ECB(17, 46)), - new ECBlocks(30, new ECB(7, 24), - new ECB(16, 25)), - new ECBlocks(24, new ECB(34, 13))), - new Version(23, new int[] {6, 30, 54, 78, 102}, - new ECBlocks(30, new ECB(4, 121), - new ECB(5, 122)), - new ECBlocks(28, new ECB(4, 47), - new ECB(14, 48)), - new ECBlocks(30, new ECB(11, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(16, 15), - new ECB(14, 16))), - new Version(24, new int[] {6, 28, 54, 80, 106}, - new ECBlocks(30, new ECB(6, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(6, 45), - new ECB(14, 46)), - new ECBlocks(30, new ECB(11, 24), - new ECB(16, 25)), - new ECBlocks(30, new ECB(30, 16), - new ECB(2, 17))), - new Version(25, new int[] {6, 32, 58, 84, 110}, - new ECBlocks(26, new ECB(8, 106), - new ECB(4, 107)), - new ECBlocks(28, new ECB(8, 47), - new ECB(13, 48)), - new ECBlocks(30, new ECB(7, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(13, 16))), - new Version(26, new int[] {6, 30, 58, 86, 114}, - new ECBlocks(28, new ECB(10, 114), - new ECB(2, 115)), - new ECBlocks(28, new ECB(19, 46), - new ECB(4, 47)), - new ECBlocks(28, new ECB(28, 22), - new ECB(6, 23)), - new ECBlocks(30, new ECB(33, 16), - new ECB(4, 17))), - new Version(27, new int[] {6, 34, 62, 90, 118}, - new ECBlocks(30, new ECB(8, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(22, 45), - new ECB(3, 46)), - new ECBlocks(30, new ECB(8, 23), - new ECB(26, 24)), - new ECBlocks(30, new ECB(12, 15), - new ECB(28, 16))), - new Version(28, new int[] {6, 26, 50, 74, 98, 122}, - new ECBlocks(30, new ECB(3, 117), - new ECB(10, 118)), - new ECBlocks(28, new ECB(3, 45), - new ECB(23, 46)), - new ECBlocks(30, new ECB(4, 24), - new ECB(31, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(31, 16))), - new Version(29, new int[] {6, 30, 54, 78, 102, 126}, - new ECBlocks(30, new ECB(7, 116), - new ECB(7, 117)), - new ECBlocks(28, new ECB(21, 45), - new ECB(7, 46)), - new ECBlocks(30, new ECB(1, 23), - new ECB(37, 24)), - new ECBlocks(30, new ECB(19, 15), - new ECB(26, 16))), - new Version(30, new int[] {6, 26, 52, 78, 104, 130}, - new ECBlocks(30, new ECB(5, 115), - new ECB(10, 116)), - new ECBlocks(28, new ECB(19, 47), - new ECB(10, 48)), - new ECBlocks(30, new ECB(15, 24), - new ECB(25, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(25, 16))), - new Version(31, new int[] {6, 30, 56, 82, 108, 134}, - new ECBlocks(30, new ECB(13, 115), - new ECB(3, 116)), - new ECBlocks(28, new ECB(2, 46), - new ECB(29, 47)), - new ECBlocks(30, new ECB(42, 24), - new ECB(1, 25)), - new ECBlocks(30, new ECB(23, 15), - new ECB(28, 16))), - new Version(32, new int[] {6, 34, 60, 86, 112, 138}, - new ECBlocks(30, new ECB(17, 115)), - new ECBlocks(28, new ECB(10, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(10, 24), - new ECB(35, 25)), - new ECBlocks(30, new ECB(19, 15), - new ECB(35, 16))), - new Version(33, new int[] {6, 30, 58, 86, 114, 142}, - new ECBlocks(30, new ECB(17, 115), - new ECB(1, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(21, 47)), - new ECBlocks(30, new ECB(29, 24), - new ECB(19, 25)), - new ECBlocks(30, new ECB(11, 15), - new ECB(46, 16))), - new Version(34, new int[] {6, 34, 62, 90, 118, 146}, - new ECBlocks(30, new ECB(13, 115), - new ECB(6, 116)), - new ECBlocks(28, new ECB(14, 46), - new ECB(23, 47)), - new ECBlocks(30, new ECB(44, 24), - new ECB(7, 25)), - new ECBlocks(30, new ECB(59, 16), - new ECB(1, 17))), - new Version(35, new int[] {6, 30, 54, 78, 102, 126, 150}, - new ECBlocks(30, new ECB(12, 121), - new ECB(7, 122)), - new ECBlocks(28, new ECB(12, 47), - new ECB(26, 48)), - new ECBlocks(30, new ECB(39, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(22, 15), - new ECB(41, 16))), - new Version(36, new int[] {6, 24, 50, 76, 102, 128, 154}, - new ECBlocks(30, new ECB(6, 121), - new ECB(14, 122)), - new ECBlocks(28, new ECB(6, 47), - new ECB(34, 48)), - new ECBlocks(30, new ECB(46, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(2, 15), - new ECB(64, 16))), - new Version(37, new int[] {6, 28, 54, 80, 106, 132, 158}, - new ECBlocks(30, new ECB(17, 122), - new ECB(4, 123)), - new ECBlocks(28, new ECB(29, 46), - new ECB(14, 47)), - new ECBlocks(30, new ECB(49, 24), - new ECB(10, 25)), - new ECBlocks(30, new ECB(24, 15), - new ECB(46, 16))), - new Version(38, new int[] {6, 32, 58, 84, 110, 136, 162}, - new ECBlocks(30, new ECB(4, 122), - new ECB(18, 123)), - new ECBlocks(28, new ECB(13, 46), - new ECB(32, 47)), - new ECBlocks(30, new ECB(48, 24), - new ECB(14, 25)), - new ECBlocks(30, new ECB(42, 15), - new ECB(32, 16))), - new Version(39, new int[] {6, 26, 54, 82, 110, 138, 166}, - new ECBlocks(30, new ECB(20, 117), - new ECB(4, 118)), - new ECBlocks(28, new ECB(40, 47), - new ECB(7, 48)), - new ECBlocks(30, new ECB(43, 24), - new ECB(22, 25)), - new ECBlocks(30, new ECB(10, 15), - new ECB(67, 16))), - new Version(40, new int[] {6, 30, 58, 86, 114, 142, 170}, - new ECBlocks(30, new ECB(19, 118), - new ECB(6, 119)), - new ECBlocks(28, new ECB(18, 47), - new ECB(31, 48)), - new ECBlocks(30, new ECB(34, 24), - new ECB(34, 25)), - new ECBlocks(30, new ECB(20, 15), - new ECB(61, 16))) + new ECB(7, 13))) }; } } diff --git a/shadowsocks-csharp/View/QRCodeForm.cs b/shadowsocks-csharp/View/QRCodeForm.cs index 27a3ab92..21ea3ab5 100755 --- a/shadowsocks-csharp/View/QRCodeForm.cs +++ b/shadowsocks-csharp/View/QRCodeForm.cs @@ -31,13 +31,13 @@ namespace Shadowsocks.View 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.Height * blockSize), (m.Height * blockSize)); + 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 < m.Height; row++) + for (int row = 0; row < m.Width; row++) { for (int col = 0; col < m.Height; col++) { diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index ccbf8cc2..16938892 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -57,6 +57,7 @@ prompt ManagedMinimumRules.ruleset false + true app.manifest @@ -71,13 +72,10 @@ - - - From 456bffc76cdaa148e0df11aa2dc960c7ebb84782 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Wed, 24 Dec 2014 09:23:14 +0800 Subject: [PATCH 03/32] clean simplejson --- shadowsocks-csharp/3rd/SimpleJson.cs | 61 ------------------------------------ 1 file changed, 61 deletions(-) diff --git a/shadowsocks-csharp/3rd/SimpleJson.cs b/shadowsocks-csharp/3rd/SimpleJson.cs index d8a3397f..2850137d 100644 --- a/shadowsocks-csharp/3rd/SimpleJson.cs +++ b/shadowsocks-csharp/3rd/SimpleJson.cs @@ -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 ParseObject(char[] json, ref int index, ref bool success) { IDictionary table = new JsonObject(); From 076fbd962651f31ca026b21f0eaa6f3a53e9b55b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 25 Dec 2014 21:10:01 +0800 Subject: [PATCH 04/32] reduce code size --- shadowsocks-csharp/3rd/zxing/GenericGF.cs | 7 ---- shadowsocks-csharp/3rd/zxing/Mode.cs | 64 ------------------------------- 2 files changed, 71 deletions(-) diff --git a/shadowsocks-csharp/3rd/zxing/GenericGF.cs b/shadowsocks-csharp/3rd/zxing/GenericGF.cs index d7b8d350..08f8ca0e 100755 --- a/shadowsocks-csharp/3rd/zxing/GenericGF.cs +++ b/shadowsocks-csharp/3rd/zxing/GenericGF.cs @@ -28,14 +28,7 @@ namespace ZXing.Common.ReedSolomon /// Sean Owen public sealed class GenericGF { - public static GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096, 1); // x^12 + x^6 + x^5 + x^3 + 1 - public static GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024, 1); // x^10 + x^3 + 1 - public static GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64, 1); // x^6 + x + 1 - public static GenericGF AZTEC_PARAM = new GenericGF(0x13, 16, 1); // x^4 + x + 1 public static GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256, 0); // x^8 + x^4 + x^3 + x^2 + 1 - public static GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256, 1); // x^8 + x^5 + x^3 + x^2 + 1 - public static GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256; - public static GenericGF MAXICODE_FIELD_64 = AZTEC_DATA_6; private int[] expTable; private int[] logTable; diff --git a/shadowsocks-csharp/3rd/zxing/Mode.cs b/shadowsocks-csharp/3rd/zxing/Mode.cs index 548ea6d7..df1a5ebb 100755 --- a/shadowsocks-csharp/3rd/zxing/Mode.cs +++ b/shadowsocks-csharp/3rd/zxing/Mode.cs @@ -41,41 +41,7 @@ namespace ZXing.QrCode.Internal ///

/// /// - public static readonly Mode TERMINATOR = new Mode(new int[] { 0, 0, 0 }, 0x00, "TERMINATOR"); // Not really a mode... - /// - /// - /// - public static readonly Mode NUMERIC = new Mode(new int[] { 10, 12, 14 }, 0x01, "NUMERIC"); - /// - /// - /// - public static readonly Mode ALPHANUMERIC = new Mode(new int[] { 9, 11, 13 }, 0x02, "ALPHANUMERIC"); - /// - /// - /// - public static readonly Mode STRUCTURED_APPEND = new Mode(new int[] { 0, 0, 0 }, 0x03, "STRUCTURED_APPEND"); // Not supported - /// - /// - /// public static readonly Mode BYTE = new Mode(new int[] { 8, 16, 16 }, 0x04, "BYTE"); - /// - /// - /// - public static readonly Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply - /// - /// - /// - public static readonly Mode KANJI = new Mode(new int[] { 8, 10, 12 }, 0x08, "KANJI"); - /// - /// - /// - public static readonly Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION"); - /// - /// - /// - public static readonly Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION"); - /// See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. - public static readonly Mode HANZI = new Mode(new int[] { 8, 10, 12 }, 0x0D, "HANZI"); private readonly int[] characterCountBitsForVersions; private readonly int bits; @@ -100,27 +66,8 @@ namespace ZXing.QrCode.Internal { switch (bits) { - case 0x0: - return TERMINATOR; - case 0x1: - return NUMERIC; - case 0x2: - return ALPHANUMERIC; - case 0x3: - return STRUCTURED_APPEND; case 0x4: return BYTE; - case 0x5: - return FNC1_FIRST_POSITION; - case 0x7: - return ECI; - case 0x8: - return KANJI; - case 0x9: - return FNC1_SECOND_POSITION; - case 0xD: - // 0xD is defined in GBT 18284-2000, may not be supported in foreign country - return HANZI; default: throw new ArgumentException(); } @@ -164,16 +111,5 @@ namespace ZXing.QrCode.Internal return bits; } } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override String ToString() - { - return name; - } } } \ No newline at end of file From f97f38bc46047414e916b710e43cfd49e3199f35 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 25 Dec 2014 21:11:57 +0800 Subject: [PATCH 05/32] update changes --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 444638d9..ef9d706d 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2.1.5 2014-12-25 +- Fix QR Code compatibility with iOS + 2.1.4 2014-12-20 - Fix crash when remarks are too long From d6ef6ba917ccd8f8180b691566977a98927a34a9 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 25 Dec 2014 21:31:17 +0800 Subject: [PATCH 06/32] add upload script --- packaging/upload.sh | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100755 packaging/upload.sh diff --git a/packaging/upload.sh b/packaging/upload.sh new file mode 100755 index 00000000..82f48b06 --- /dev/null +++ b/packaging/upload.sh @@ -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/ From 20023339d3792ae250a89480bf1104d0770d4cd7 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 25 Dec 2014 21:49:17 +0800 Subject: [PATCH 07/32] only left button will trigger double click on notify icon --- shadowsocks-csharp/View/MenuViewController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 2bcf4cd4..2ff0e763 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -59,7 +59,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; @@ -393,9 +393,12 @@ namespace Shadowsocks.View Process.Start("https://github.com/clowwindy/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) From 8043f34d3c5b8324451d346515b048ea4e21987b Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 25 Dec 2014 21:50:10 +0800 Subject: [PATCH 08/32] bump --- CHANGES | 1 + shadowsocks-csharp/Controller/UpdateChecker.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ef9d706d..de4f3199 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,6 @@ 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 diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index ebf6e3b1..a7683318 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -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.5"; public void CheckUpdate() { From ba353a506229bd4c119ef8227c795caf3db03007 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Sat, 27 Dec 2014 22:04:36 +0800 Subject: [PATCH 09/32] close #99 --- shadowsocks-csharp/Data/cn.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 3feaeb98..ff77ebde 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -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...=显示二维码... From fa82d6b93d8b74dcebcc154ebdd0c2f88589f966 Mon Sep 17 00:00:00 2001 From: kxjhlele Date: Thu, 1 Jan 2015 09:17:33 +0800 Subject: [PATCH 10/32] Update MenuViewController.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改关于链接到 https://github.com/shadowsocks/shadowsocks-csharp --- shadowsocks-csharp/View/MenuViewController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 2ff0e763..b12e1a29 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -390,7 +390,7 @@ 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, MouseEventArgs e) From a9aede0bad7828ca405032d3135e0392564cd060 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 21:21:44 +0800 Subject: [PATCH 11/32] fix #106 --- shadowsocks-csharp/Data/polipo.exe.gz | Bin 65617 -> 65830 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/shadowsocks-csharp/Data/polipo.exe.gz b/shadowsocks-csharp/Data/polipo.exe.gz index 836135111d80aadcead87cfcee734138933697af..c7038e1247bde4b3ccc2443e71222bbb8a6ffb6e 100755 GIT binary patch literal 65830 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

r#grVgua=(tYSo|B{#P%H(f_b6KR}y);9UI2 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%0A}cW)^5( zt2%~Pj;-thI59BIiu2JiTb=LU=&&AC;}E9bp7`Ut$d?nnaWiKOj3>!fbd3w~4IIEP z!A5qG%Qv7G#mo*ZW;{6E8Q^^rmS%f(buBETsm1UPKD`%hMT*n0Rt~L2vWQvgGV{`g zDa+zT4-x?(m$&^P%?>-1t%1bRkUI1W>IQRXm7MC>cWK{5f%FekAvhzDcPdcSp+3*x zBg@$s#iNFr%FlpEq+gbDO1EfFfN15dcvttogWTFMV{>!oX?+_$K`S8-r`_a>_{_UY z5w`Xn(8Ses-f#8_)aUWyx-DM$rxH9H%<<9V#rn zT6j(-BOOaA@J8{#39a!Um2mO&lGk!jcMdgAKSZ-=L-^?i}DE3-WjN+q}c2d~0()T7!r z1dPZuQvyY&n!Km4fS(dr(RnGZl3eZ(h(}L)Y*wqH6^^mh~UTymt((%Mj zN|Wjv;h|NXx3@gHCTo(l+Iuuj+R%vG^YK1&Qbcv$wi@r=n!LUBY6Ny%HI?b#PP0Id z<3EyIot1X3#(T70wfozgeVRoO_~Cm`c~XscTTLDUqZ*FDddlWMl5UV79A_|%_&XIz zmG=jwzwLTG%$}y%8|`UR{f#z%lRZtU4NO1hTvZTc^TTlTL`=Hrti)i3Zs2Lx12Jx98#=WZ^BmfCV{6@qfZLEMJqW#t)%B+x{c3&HrR_H zWqXOTsLcCuyGdVE9M8atr8Cz@@Vpe{h41(f{t@4uni$+iDRrsmLp(U)kqriHinjh7 z-3UAE=i*Srd}L#!nMB7%Fz*)ady{UJ?rIlEq4-g=9_Ep*)1qH0yxB~XN;FA=#$TFc z(a#?8J@7HD=51bas**EB{(Q_X_lfd;)*W*GlqQdd`}eRh2k70?xlTTr6aZfS~w`O7p z*kYK$kFVyugJ4X4surzhLeCN>OTp?LNIBf1{nR(YqWvTs1b)mP44ocB|L_ptMMe^Jc5u_OkRzFwmjyD_fQrq|i!_6zImzADB8%=GuP z`Nqf{z?1h~wxVZ!D`uQwU7u5|W$owTA3R4b$wRru_@!HYzr%2RsqX3aoYWJP zl(mYsL3TMa6>B~JIgZZR4s*f8Xie+&(1>lXD6v;^AG>oD0gPfk8f;Vm{w^K?+_??!5_z^ZK#+vOL!9lsoDZMtfT7N&Z=)ggI&T#60k*n7sUX3N>YA;yZ0+1e6C~5PN<$lbFe0xSZ%A{DKHN=)^hL%L`XN9fyvcZA)&!_;_7R3Qey&K$l zN6Uw5eKXVM9WFc6-pvD}eVY4Y=cE7P1^r$SERQ6+PX}07ThdDHWmDu*yEa*|!qm+< z%iAVfm03XhcPoYc?e2WLGY_LM{yRvQC1G@syGi9pSJLDH1N|nVU3yxv_qS42DAVj7 zu&H=Ub1MUsd57IC&e`k-7(q&}!YOulp#vQ8M=net`&PMwb|bsLA!^vy-v(t3? zlg zu+=@PFYDHeF{=STYF;G~;fnt`bmW=i&N}#`*z$dCCjN})KM<#l@LdJsz;r8aj1Xht zKh30lz6I$I%h`+59aT0VFq0g-KMHg3MtNyUl2>p>g-Ympd6r#zK&6-)Q*PFvV@_^s-W3i5kOWm7!_ zL03W=5_pR07u|DK4Fw6hllrGW)4>#Ct_8RU$c4cR&&d9*$wn+ODGLQ}E>=D!oDgH) z%5xFw0@1`;Ph-kL65GBN z`<7?H)!=yBjmS02w)Kg~(_s?K)8*nWCut;9bE^u(4LrTqqd$8y4W8{z zvq3l78F(VN0>Rvb+SJ$UNnhO>A;sbi-!jyv`O8s&$CY0L8&h5-3`f6UjIWSXx>&QV z);t*ug6ch@ibAxr(hV$cZGPu;tKByihTajPhg@eag+rs0)-ql#_|*u_hF@!@3t8}A zc@C~99$&O>M2$O>tv)ATi5qM6MS-uw*O!f`pDsgC@Ab;=+^KpP^#YF zkL&*1JGctMz##Zd{+h3aa?ET01$ng9Mwq@4M18m!IO@qWQ`i7kbpm_Kmj@ea-81rW zeJwOvKl4siigkoFvZDGCO~>t4DKYTi*{w>Ix6b^iu#m@seG z`M#xvdR62sY`Hc+9v+*cQao9Yw@8oo&#-tO<%OH3wdaEbwu~!tt!!=wwIaH63=CMu zv|w9uL$gv*SOxgKcbqHzyvQfPDA~nhy6@RTW*)XdWYvK^^B6*9?~HQ6sIFor#i;iU zP|DvKS6+Wl6BBwjjLXi)m7*h|mCjtzoxhba-HY}f^6tIyVEU-mxccv>0itNnEhS3P zp4P~1c&pqMTLRC40}EOX&D(om!5*c2uhthZ7)XilWKssfyNFN_g2r63C>=400QA24ZgrWH};mnW~(Tq(#B7T%MLx6%-^HIKT#p-4n=)79^uU0;IK4 z8b}9k#SEI8k4{zMpFiLb@G|)(d(T{erSruV5sGWghx{0yG@jf@ln@I7Fl!5{cU4d`bbmUW!c8)9BX1MU?*lUMt zgpCkI4xH?1j7a3(uX~F|F#btyFsL`;_LcYp1~^v~hW6VqS&0pwdfigC1{~+z2AF(k zr+v3gWrO)bk-HQ6j9vbnxJrg{mstw-JtMehO`zKW3dHRIP4d2zFUj6og7ANM2@R^X zfZ2ztMkAjxVRkrEv@JP*bTBiKMYHlcWYMs68$Qd4xa+^vw>@I~BCTd2>PQcI%ZO3AA zc_(=zi=ai8QYf(-Q_~XH`!1dCZYn#;*ZxGBDtrxzwBsQQq3i}yH!{u_`XwMgVsM}jWs<&pNajQS%7<=uM?YDEbu;ng46XtBu z^K8i3g8VGrpG~_zE4Neo`5qP6V=(Gnc9@oA;~zPR^8m<8(hCpnZ+(zsCf+9g`LrMc3p91!RipJ5vfhN5l;NVh2`3j ztf7ci7A4yjP2pXX4;_A5a+q2CK7b;!qrN(Wt_`0rj%0Z;aW^Qr*`56()3E#MdRn$L zd6L64Qlz8#gmPtD3-GfMpn^}NSnAqp!@X7dCQduwQ%CGJI(_$`Akv-wCCNCi#b!+X z>oDGO$xJxT~K5fA8D(rp5!}kE-;2mg2S9rJQI>wK+7LrDlGcfhx!5PcOYHMG&2NJ zHXRus!Fx^7FKogGW&`gvCKC5Aa2u7 zor!j~G7L)j5i~Cp+((wr6?9#kN=JNm>Dsm{h4O7A6mf>;?b+|mnm0H6cMWFKz>Jn& zESClC{DOvSEWO4daqdS*=Ji}LdYsm`f2%_VAPms5`+FUr#j!}3$JYEypj7F<_TS@| z#@*@%dmAA=NHL+@khy*c#0k=|?Zu3Q7Z1Oo}KofPPu-lNv_%}BHMBm7}VoMVhs zWne2_ifC+$moFsFglfY=&^up-g?;k?1K#KWg%W{M9Y-*o8}dufF&*ux zZwIYYs1hsUIm_h~oQSX503SV$?g*zm_5e}xbOHM1BlJRELt&qAn#n1o^7FRAVEJ}T zjbs8xL5OGm=e66KE7q7{Hii5Rf%1JChhbuDTLc-TK4#ITZU$x z?n(2ul^s#C#~b}4zr!ehtoqGDhUFS;+~anu2va}Ccg=vryNhx?oO7Lsq4iR@Gu6dd zdch^{?Fh;9DUKIj+OHQ|JIB4^fa%w=Eu9Prpm?;E2p6H%)6L4)ts{7kVqA?`60{juMPq>IXWhcx8OQq_WY7DZ zHZibpb9IA!Qh|PTds5}uq0a1vn#94Ik}Twfxw+5h)Nzf!xO&NXQwq z2QoG!e9o8m`ufADI(H021#Lx#eZ{Y@FFCt@4`EY%me9#=t%_Z10~4~n>K#m)7~FeU z)L%SY8>Hx&Sg}&#N`Xd0p{A679H^|#wM>V0MOWZ%pzE_vRm(MY$wLCkfg!VUs=KO( z)aK@-xZ!yrV8*oRs*YoCwK3$LHqP@2JseJlV73w=I>>n)7~e8;j;E`7SZ$TX9OEmE zAT`;-kIh}aN;4|3ZCu4ZkEJ}mE?TV|XSdzC&Vw+e$JgsRvgt|BkUsDz(bbUu^UaSD z0*Q$zLb}6(SPR4=1i%@Q+Qa_7+K0Bf@5QhxVkKD@ID(MB!Z84hK55=NeSdnNv)z-y zG8F|mF+wwAIKRb@_y%2CgxD;(zKoK2pwJAi;B`*1eM4CFx&<(7S^br68j~aX#l`!V z)JOeMuTzS9LG7BT2RtQ#tPKe{wS7xGF|(XKRR#X7NKBU|7LMGa}`{Ocp3sRJOs%7el|8qM@#sy##8fVR%x2ImmX%^LGduN>V9wEL%t<-HRL{A zbA4UD*XKiFVcZ7mC>rj*6@V2ZemDK3LBHM_pXclYZZI~0vz5Z-`3mctd)>VA%|byc zBI&J}s=db0WJYbSeLR^4JnWg{n{URm%HhDM+{K;|wN=B+Bs9M#f{zCQ^UMv_VUW+Y z=8pHodfyJ_j(3mn_aLRN#q$on{Q+i`dS+J5R?W=MBnRIXVQy1^8?VI9$O?f*|L$?7~rx5(vu+gBQ_I!O|*O0PRg`&xexX<8jl zfM9_Z(KE>y)PQ*q_?+)?vvL9gtbGLSv*rLiM}U_DoZl7(^sRvI7j5-fq(U?#%+qWJ z&;n((sRh#hy-kP&&n7o0bHM~@e36_PM>esT&SLBZRg=9lq9GN6?HQ^wE!s!R-1Ea38EJvJdhataatZz2!wQc4?cT4WpJ zEZS_|XSLHsqXIg-u+Y|GAv)k=q^<7TCOXiyu=e&r+s^z5uxjYE|7IQu@HXyXht*9$ zKSN8t(`4cZZ*G%hU7j?BZFDI(JZPU(NH8V2sqs$;+wx&iO`!THBxV*p=AF@uXn266 zR9H10OP>Ka76JYy0nXOo&5}1kBBvCeEY0wVpjZTRL{KJzMIuNM@`|Y(`Nbwlq`@$C3BT^-GC0W`Dku$QX{rUz(M+%{&hjRM=25R5%s~faj-L?Kl6C-%p7R$vWX;AM zp3hht>~sVfnR$v1A;TP}pmHB$+qBnw3Z-Eu(@xF^2JzEZ@&+8~Rc1oJMVuBsy-jF) z%#I;KlerP!Y>V@tQod0sX@I7Ob)2J{UE|A{_#Duu#o?b13lZiWv_R)uorN1c_xKXV zvHUVNILcy`SvFIa@>=ar$fB0lVvMbp$>91}8Ke;)v@Jf*rMkbMmNz)dH+oW0{cDkc zGh*;_iNQAn?5)21DC|yzzy$MU0*sP?zd9#w3k3iq(~;fY53O_6@{RCKqx6ChNXyec zb;$M)rS7Kor?;AWwRv|1gZM3>l){Z5)n0(oEln-lsHLme4Mq>uY1UTQK%?82AMI@Q z!iJePavDbF8AJred8-@DD?d*F-3EYjSpbMXPi9`xoYz=Rf3Lp`c#(Uy zQO#43^x8$lYH3JEk`qZSPt5oQPJ2{gTnP^hwr9j}tJ;qts z;O6aT!}$;w<`G^o8ps^lyBLK^aSF?sDJx=MqZ<@fIW~Ys^KHhjc%Z7~>mlz24h78~ zOnk8)yd4oX*S8WH?=9tt8sdb#6ArYKfSLsm;aQw1T-&*X^mneW@I?e!LaZ2RZy-n# zr|tw_;T8mT%oYT(Q1wE&yrLt_kYSn(Q#l;$=(|7)80TeU+5XxHroWPxP0s{RkQD%O&=*PG zDd}}ioZI)KIPVOoo+Hmp7YV`7ED*XYjT;fER(DEydC7Od2*Ajz>l0_bcprGIQ5Sd| zLp6$xzo@J54AdXF>IUDem|a8YkZcElHuk(Y^V7pRI??uWxA)T_il@Q*p#`s~o(kK` z2VSG8?3)<@>uFd3(7SbNVFNy#g>{}H{8UP6X@VzHpOw@K>2eh1ZL^b1=DcG>js_OD z%o0q8F9T9|lgVDn?2ID9ck}?hMCQ^KI&cJTLJISE5eLrhbdGJli7=m#i{Fqo0etmY zOv1o02jqO@9EE}wow2mcZ_{g0r@Rbt)L4!>Y7*?)aq#m@MqTk`Axb95 z?*r05{}SCUd2*4LeB0fHFJjX9JX>%w!!r}~DK7j>p7c}<|NKmP+{?!}JPlVmsAXMc zGEMdx3q~8^VXMD{;U)J>NK>?HSC0XWazf+6bk?GgXuLBQ)gOV3&33!nM))2jKo0-| z$1wJ=+p3ReLkj5rEbM6N6INk(LRr#)aV8!H@0aW4k1hy@EmVhT39URl*R)va9LoJ= zU0bi#K^yNJ(B>jzaJa2JsTBFnY0ZJ%2lMRK^o*1i^lVVD}O1Gx}f|8HL_>LRn*l z{T_ObaRWs6M$axv1fI2o=VXcJPLQ0H5_CP7o9bJH#ZXTqos2AGMl`v?#e4pJWMV7{ zXhewkyAo##?IG<0_+p`>T7+=~Wty%Lw)IDJbG=x-?JVVKa9d_@L8k>~W89y*NK!5v zaegOEV}U8}h*qpH)();Oym0NMCplI*shr26?x!UN&NMduMjSdFr{E4AI(Mhn(GH6U ze7dtBjNC{EU+13cG@JvafYr6qRk&BWs)1C|MPtoc-jnQl_%@=i&oB<&%0M6O;Qqg3 zp#NzCTR%e~=8JN7GURxka-2g%;E)t^26W|AT6y$0&bGphOvGZyUJVGTvqyehPKJ7O za7+Fx(i^vgT~NfOcoYm8i>r;JW#DpS^PV8u#BHYNj>hK@fIG7nf}Y;WUOZ@$t)i}g z73XJ`q$fp9$0-&kzQ~9tA<+J?NQkF+zDzx8)q6CPLwrV<1|&DnjAt2MjG(C@V`URB z4wjlf`MA6tydq?~&Jz&=Q*et`xV7q3s3U@^{lv2S(>`0_{v(hhy6L}STf`#ZttTs;ZmS5RPz;TohXZPe79TAAt0Xzq*|V` zi@(bNS)L4m#gc(X!r_LR)+%i(aIoX$ZlW zA3<1e$5-);e(b3$bEy8?dqUl!q0?o1@2O((cfXf*ERN!3iL;yd)R16$#SN-Ae-nQQ zO+2%yVki{|H0SrwV$JgIe9+frET#YtDYbHmNld<&Fh6+wkXJ09UG~xH9$~gJkm#*W zHMt>rluFUt5zVI7t3vK+-mTCJusvH3Eby_JO1r6cH+`AhjM7WUY0R~)f`&&D=}ML) zK_O9yyB<_7;Q*E9H;(?q;$< zJKq|wzC^?nZ6teimS^p3wK{LkK4c!{t~VryNtx;i#Pmhk%cUg&-;uzRZTmQP(n zXg%C(n1ORJz=r_|c=>1dGDpCL5h_~b8c|)7#PeBnWv@2+pj63%FYPiEBf2$w9r!Lv zU;(Lod*IR6hXP8;l5JFaC21E1QoXC0xW$)3#Py^OKsHmpd$mhbj1DRbiE*6#+8QM7 znt%pU@8c**KaqOx?*~&&-ww-RRTCaK;Ob!QG<8_>3&_v>jb3(P@Hku;?1S5a1aZYV z|20(Et5?}^6;*y+`Va8j!M+2Mn*W5H+L9?oz+YZv`~GzPG1~WkZ$0u)mR+V!<3p51 zU18NGK0~T(jt==6`ZXMrK+CLc6vrl?Oaz)!L~hpVeFwiBf7T zc4^Mr%)Z6BurGwz?aw(hvuMy%FIV3qp8TXM#uIU7c-$r|ntdR15V@ zp~lg380NR2?%8b-HlZb_6`66u&RUfOwgF5WS^Ka%w1fIE#Bhv)5!yL)Lvvd%o7Z>? z0q`exGy2p{xg^ymF%O4+iMCS+I70r~1Q>TLEH9Bi1hu3ka0l4RPJEU$xfAehDQSYm zWu#B0A5BEGLno>C3!8){d6UR^h<4y}TKz3zMNgI0g^tA9GfPF%t=A@1B1tVF7l`Qx z31LDm(^AqR%5>bqR;;~!rS5ThrZRCOxWmw@sVIa;3;ZsP8Ca-nn7v#a3R(f%gmfjZ z9IuwVC`+PJa%3sA%uz{xD2bEA)r|(2QbSD#kd6+4I2n15q=C7iyxI1`p6J8tOAfi` z)pe)~GTrIuOv?C(p}BXX1{&_biI>z`6ciYT2m-7!08%P|v@eR9OrE7`$$s_TY;wU* z5_PrJhj1Efq7In17&as8$U2Mj3HbltOe5_HI}Z2X<6j9uG3UH9XhxYlYrQiz^N*D} z4ZnkW1LZtAzbr>*Wu~F!TMR9K2TF~M3CO7vR=e@5h?MA|hh(ukkxiDO=l(8oduL>! zW6a7q-+k=NXiP^>hxdb&fx=oI6jO{mWkPrnCEldYFGg^KR0!4~Y1pAp6DCuc#U$k6 z`4WhsCem>ZA~?6HcV{A)EO9_iY-Ds^LPkdLkfB{YOX!s(1gbaUeFMyqB{V9`yXa6R zA^DU>a32E>A}Ewi2j8|tY<6>VH8{1!*(3d zbximsLy9Kz-qH2q!xd2M$Bpq)EDSy_mZf$Nv8oRyh;{x`xy~o|2|rZ`wA*HrI4gwEgU_r8@#%{qg@4_t2 zbqrZ)U^|O*tDrB^=l_kYU$kWSkg%3iQcE7aM_$81h-pub1zmnbsV67V84#=@&;nZDLU9c396knf8@zL5-Hj=UT zPQ0u=)_R=>H04A{D~MHsiWZZZkRlG~_ixU%i{Hbf}{{V%hjodBKigXGD|9XB9dXan}m1gyP15%{i*mTWJwtAu^U{}zDA(*Ifm zCijJ75^)*1%>$S~87M-1-0GPCIZ{UpnfrVuWM&FRN!~_5+82QfV8LuRcje?|)r?0Z z75#8{(W9y8pBD=QLHA^jhCxO! zk)5^~CBz>9-z?l+sl*M40W08yQzS{N$zJ5=WjSM=z(~Vj(Cv)@m~<+gV8#07J!kiJs-=6OT_#;zGc*;%Jp}nd&#IiHE%^O zsqZ{&W`|l9+tWMo3xgk5Udc37U2MTDKLau$VAU+dc=F}eQwmE@dLkh+7`Tf?D4p2B zOrELUCz4H`$tvDjt=Xg_rNE?H(^sfTorr9+@=(B2u9};Tr;?cgsEWDZ!ldeFr1!?w z`~LVcRv0?xk!ged0-AaBs^78bSs9u)>ZJ)O%boP5Rx>m|KJMbSI79g3F=l zmoSFj;bWSf;as}RErSkMDSfq2+*)B6m) z=jg`p%UO|8^$c!IC1)y!5y7(>{2wEk>70&H^*L|Qymkobv(&_^3v$uDR>*t1An@G_ zC)K3%kiL^NAnfphGBZfOk}yQ>z^_J9{!kOM@fYKwF&81W4wlai)KK%Xo)tr+0o(dx zJUS|(7C%eQfw4xZz@Qk8JNlVXAa;7@B1Mzp)*r^S?P~ir1mS=Zq z$cwMPRa{|XW5`EPE(uh$@(pUSvr@XHDzSvEthF>A=j5YH4nUQI@^6v+3uU35-1GgNQ(`%H?&LdKcQ4AMl)*N-#Qsur<8r8F|9o1azT$dnsxQ;kZ+DW0DLectdT#XMm~~9 z5LqTq8Y=n+*}*E3dtdx3{DJwcOV%GwMoXsYmc6vO_*55?4v1T@?@brU`CgV#<<1;< zBwm9xhE{oxjfpUn#bsW{0xfW?y~2L8KvWYb<$oNXJWzLwdDu++7V@r7b5ZzF$9%*u zFaJs=TDg+VJkqdT!uL9vYD~vHZ`YEE@alD5jZj_8oZ-Def7Mz(MvBKFmp3;PvPAq; zW>}ckBrqbM3=_95L9w z7ZKJEC#fI);-Vv8CZ;+xEwiNAwVdQ{gLOU^Yx4;D6t>sS

EJMf@L!m-8u=^8=LA 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 z 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 Date: Thu, 1 Jan 2015 21:55:43 +0800 Subject: [PATCH 12/32] log more exceptions --- shadowsocks-csharp/Controller/AutoStartup.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/shadowsocks-csharp/Controller/AutoStartup.cs b/shadowsocks-csharp/Controller/AutoStartup.cs index cc7e0b2b..b040445f 100644 --- a/shadowsocks-csharp/Controller/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/AutoStartup.cs @@ -15,7 +15,8 @@ namespace Shadowsocks.Controller { } runKey.Close(); return true; - } catch (Exception) { + } catch (Exception e) { + Logging.LogUsefulException(e); return false; } } @@ -30,8 +31,11 @@ namespace Shadowsocks.Controller { if (item.Equals("Shadowsocks")) return true; } - return false; - } catch (Exception) { + return false; + } + catch (Exception e) + { + Logging.LogUsefulException(e); return false; } } From 07dc69fbc9416f77ac94a0ab5bee734ef4266ace Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 21:57:28 +0800 Subject: [PATCH 13/32] format --- shadowsocks-csharp/Controller/AutoStartup.cs | 86 ++++++++++++++++------------ 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/shadowsocks-csharp/Controller/AutoStartup.cs b/shadowsocks-csharp/Controller/AutoStartup.cs index b040445f..36ad775f 100644 --- a/shadowsocks-csharp/Controller/AutoStartup.cs +++ b/shadowsocks-csharp/Controller/AutoStartup.cs @@ -1,43 +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 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; +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; - } - } - } + 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; + } + } + } } From 5010a01d14fc1c87e9c49823d8ce872ad2bf66b9 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:04:37 +0800 Subject: [PATCH 14/32] move encrypt package into encryption --- shadowsocks-csharp/{Encrypt => Encryption}/EncryptorBase.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/EncryptorFactory.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/IEncryptor.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/IVEncryptor.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/PolarSSL.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/PolarSSLEncryptor.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/Sodium.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/SodiumEncryptor.cs | 0 shadowsocks-csharp/{Encrypt => Encryption}/TableEncryptor.cs | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename shadowsocks-csharp/{Encrypt => Encryption}/EncryptorBase.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/EncryptorFactory.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/IEncryptor.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/IVEncryptor.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/PolarSSL.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/PolarSSLEncryptor.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/Sodium.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/SodiumEncryptor.cs (100%) rename shadowsocks-csharp/{Encrypt => Encryption}/TableEncryptor.cs (100%) diff --git a/shadowsocks-csharp/Encrypt/EncryptorBase.cs b/shadowsocks-csharp/Encryption/EncryptorBase.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/EncryptorBase.cs rename to shadowsocks-csharp/Encryption/EncryptorBase.cs diff --git a/shadowsocks-csharp/Encrypt/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/EncryptorFactory.cs rename to shadowsocks-csharp/Encryption/EncryptorFactory.cs diff --git a/shadowsocks-csharp/Encrypt/IEncryptor.cs b/shadowsocks-csharp/Encryption/IEncryptor.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/IEncryptor.cs rename to shadowsocks-csharp/Encryption/IEncryptor.cs diff --git a/shadowsocks-csharp/Encrypt/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/IVEncryptor.cs rename to shadowsocks-csharp/Encryption/IVEncryptor.cs diff --git a/shadowsocks-csharp/Encrypt/PolarSSL.cs b/shadowsocks-csharp/Encryption/PolarSSL.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/PolarSSL.cs rename to shadowsocks-csharp/Encryption/PolarSSL.cs diff --git a/shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/PolarSSLEncryptor.cs rename to shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs diff --git a/shadowsocks-csharp/Encrypt/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/Sodium.cs rename to shadowsocks-csharp/Encryption/Sodium.cs diff --git a/shadowsocks-csharp/Encrypt/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/SodiumEncryptor.cs rename to shadowsocks-csharp/Encryption/SodiumEncryptor.cs diff --git a/shadowsocks-csharp/Encrypt/TableEncryptor.cs b/shadowsocks-csharp/Encryption/TableEncryptor.cs similarity index 100% rename from shadowsocks-csharp/Encrypt/TableEncryptor.cs rename to shadowsocks-csharp/Encryption/TableEncryptor.cs From db6701b1b2de6e6a403147449e3d4a55eb606520 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:05:16 +0800 Subject: [PATCH 15/32] refactor package name --- shadowsocks-csharp/Controller/Local.cs | 2 +- shadowsocks-csharp/Encryption/EncryptorBase.cs | 2 +- shadowsocks-csharp/Encryption/EncryptorFactory.cs | 2 +- shadowsocks-csharp/Encryption/IEncryptor.cs | 2 +- shadowsocks-csharp/Encryption/IVEncryptor.cs | 2 +- shadowsocks-csharp/Encryption/PolarSSL.cs | 2 +- shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs | 2 +- shadowsocks-csharp/Encryption/Sodium.cs | 2 +- shadowsocks-csharp/Encryption/SodiumEncryptor.cs | 2 +- shadowsocks-csharp/Encryption/TableEncryptor.cs | 2 +- test/UnitTest.cs | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index 1a749b1f..cd6d2f96 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -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 diff --git a/shadowsocks-csharp/Encryption/EncryptorBase.cs b/shadowsocks-csharp/Encryption/EncryptorBase.cs index 06779103..8b5cd61a 100644 --- a/shadowsocks-csharp/Encryption/EncryptorBase.cs +++ b/shadowsocks-csharp/Encryption/EncryptorBase.cs @@ -1,7 +1,7 @@ using System.Security.Cryptography; using System.Text; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public abstract class EncryptorBase : IEncryptor diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs index 9599adbb..d5ff15e3 100644 --- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Reflection; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public static class EncryptorFactory { diff --git a/shadowsocks-csharp/Encryption/IEncryptor.cs b/shadowsocks-csharp/Encryption/IEncryptor.cs index 3ca197d1..b45c62c7 100644 --- a/shadowsocks-csharp/Encryption/IEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IEncryptor.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public interface IEncryptor : IDisposable { diff --git a/shadowsocks-csharp/Encryption/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs index bdeae866..0a59a0df 100755 --- a/shadowsocks-csharp/Encryption/IVEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IVEncryptor.cs @@ -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 diff --git a/shadowsocks-csharp/Encryption/PolarSSL.cs b/shadowsocks-csharp/Encryption/PolarSSL.cs index 79941d57..93b662a8 100755 --- a/shadowsocks-csharp/Encryption/PolarSSL.cs +++ b/shadowsocks-csharp/Encryption/PolarSSL.cs @@ -6,7 +6,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public class PolarSSL { diff --git a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs index 83f64f09..6216c24d 100755 --- a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs @@ -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 diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs index faced736..9bc72d32 100755 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ b/shadowsocks-csharp/Encryption/Sodium.cs @@ -6,7 +6,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Text; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public class Sodium { diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index 8b7ac5b2..5d6165eb 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public class SodiumEncryptor : IVEncryptor, IDisposable diff --git a/shadowsocks-csharp/Encryption/TableEncryptor.cs b/shadowsocks-csharp/Encryption/TableEncryptor.cs index 1382d7ca..3dd526d4 100644 --- a/shadowsocks-csharp/Encryption/TableEncryptor.cs +++ b/shadowsocks-csharp/Encryption/TableEncryptor.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace Shadowsocks.Encrypt +namespace Shadowsocks.Encryption { public class TableEncryptor : EncryptorBase diff --git a/test/UnitTest.cs b/test/UnitTest.cs index 94fa9053..8fdf3f28 100755 --- a/test/UnitTest.cs +++ b/test/UnitTest.cs @@ -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; From bff33ae5c83acc57b5683c99e370067c5930a04d Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:37:07 +0800 Subject: [PATCH 16/32] remove some code --- shadowsocks-csharp/View/MenuViewController.cs | 177 ++++++++------------------ shadowsocks-csharp/shadowsocks-csharp.csproj | 18 +-- 2 files changed, 61 insertions(+), 134 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index b12e1a29..00150e58 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -28,15 +28,15 @@ namespace Shadowsocks.View private MenuItem ShareOverLANItem; private MenuItem SeperatorItem; private MenuItem ConfigItem; - private MenuItem menuItem4; + private MenuItem SeperatorItem3; private MenuItem editPACFileItem; private MenuItem QRCodeItem; private MenuItem ShowLogItem; private MenuItem aboutItem; private MenuItem ServersItem; - private MenuItem menuItem3; + private MenuItem SeperatorItem4; private MenuItem quitItem; - private MenuItem menuItem1; + private MenuItem SeperatorItem2; private MenuItem modeItem; private MenuItem globalModeItem; private MenuItem PACModeItem; @@ -121,26 +121,55 @@ namespace Shadowsocks.View _notifyIcon.Text = text.Substring(0, Math.Min(63, text.Length)); } + private MenuItem CreateMenuItem(int index, string text, EventHandler click) + { + MenuItem result = new MenuItem(I18N.GetString(text), click); + result.Index = index; + return result; + } + + private MenuItem CreateSeperatorItem(int index) + { + MenuItem result = new MenuItem("-"); + result.Index = index; + return result; + } + + private MenuItem CreateMenuGroup(int index, string text, MenuItem[] items) + { + MenuItem result = new MenuItem(I18N.GetString(text), items); + result.Index = index; + return result; + } + 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(); + + + this.PACModeItem = CreateMenuItem(0, "PAC", new System.EventHandler(this.PACModeItem_Click)); + this.globalModeItem = CreateMenuItem(1, "Global", new System.EventHandler(this.GlobalModeItem_Click)); + + this.SeperatorItem = CreateSeperatorItem(0); + this.ConfigItem = CreateMenuItem(1, "Edit Servers...", new System.EventHandler(this.Config_Click)); + + this.enableItem = CreateMenuItem(0, "Enable", new System.EventHandler(this.EnableItem_Click)); + this.modeItem = CreateMenuGroup(1, "Mode", new System.Windows.Forms.MenuItem[] { + this.PACModeItem, + this.globalModeItem}); + this.ServersItem = CreateMenuGroup(2, "Servers", new System.Windows.Forms.MenuItem[] { + this.SeperatorItem, + this.ConfigItem}); + this.SeperatorItem2 = CreateSeperatorItem(3); + this.AutoStartupItem = CreateMenuItem(4, "Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)); + this.ShareOverLANItem = CreateMenuItem(5, "Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)); + this.editPACFileItem = CreateMenuItem(6, "Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)); + this.SeperatorItem3 = CreateSeperatorItem(7); + this.QRCodeItem = CreateMenuItem(8, "Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)); + this.ShowLogItem = CreateMenuItem(9, "Show Logs...", new System.EventHandler(this.ShowLogItem_Click)); + this.aboutItem = CreateMenuItem(10, "About...", new System.EventHandler(this.Config_Click)); + this.SeperatorItem4 = CreateSeperatorItem(11); + this.quitItem = CreateMenuItem(12, "Quit", new System.EventHandler(this.Quit_Click)); // // contextMenu1 @@ -149,118 +178,16 @@ namespace Shadowsocks.View this.enableItem, this.modeItem, this.ServersItem, - this.menuItem1, + this.SeperatorItem2, this.AutoStartupItem, this.ShareOverLANItem, this.editPACFileItem, - this.menuItem4, + this.SeperatorItem3, this.QRCodeItem, this.ShowLogItem, this.aboutItem, - this.menuItem3, + this.SeperatorItem4, 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); } private void controller_ConfigChanged(object sender, EventArgs e) diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 16938892..a7216f48 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -89,15 +89,15 @@ - - - - - - - - - + + + + + + + + + From e26a63737db35ab23c062d8d2dc8e0f51c7b3c55 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:43:40 +0800 Subject: [PATCH 17/32] remove duplicated code --- shadowsocks-csharp/View/MenuViewController.cs | 52 +++++++++------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 00150e58..cb40de2a 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -28,16 +28,7 @@ namespace Shadowsocks.View private MenuItem ShareOverLANItem; private MenuItem SeperatorItem; private MenuItem ConfigItem; - private MenuItem SeperatorItem3; - private MenuItem editPACFileItem; - private MenuItem QRCodeItem; - private MenuItem ShowLogItem; - private MenuItem aboutItem; private MenuItem ServersItem; - private MenuItem SeperatorItem4; - private MenuItem quitItem; - private MenuItem SeperatorItem2; - private MenuItem modeItem; private MenuItem globalModeItem; private MenuItem PACModeItem; private ConfigForm configForm; @@ -146,7 +137,6 @@ namespace Shadowsocks.View { this.contextMenu1 = new System.Windows.Forms.ContextMenu(); - this.PACModeItem = CreateMenuItem(0, "PAC", new System.EventHandler(this.PACModeItem_Click)); this.globalModeItem = CreateMenuItem(1, "Global", new System.EventHandler(this.GlobalModeItem_Click)); @@ -154,40 +144,30 @@ namespace Shadowsocks.View this.ConfigItem = CreateMenuItem(1, "Edit Servers...", new System.EventHandler(this.Config_Click)); this.enableItem = CreateMenuItem(0, "Enable", new System.EventHandler(this.EnableItem_Click)); - this.modeItem = CreateMenuGroup(1, "Mode", new System.Windows.Forms.MenuItem[] { - this.PACModeItem, - this.globalModeItem}); this.ServersItem = CreateMenuGroup(2, "Servers", new System.Windows.Forms.MenuItem[] { - this.SeperatorItem, - this.ConfigItem}); - this.SeperatorItem2 = CreateSeperatorItem(3); + this.SeperatorItem, + this.ConfigItem + }); this.AutoStartupItem = CreateMenuItem(4, "Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)); this.ShareOverLANItem = CreateMenuItem(5, "Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)); - this.editPACFileItem = CreateMenuItem(6, "Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)); - this.SeperatorItem3 = CreateSeperatorItem(7); - this.QRCodeItem = CreateMenuItem(8, "Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)); - this.ShowLogItem = CreateMenuItem(9, "Show Logs...", new System.EventHandler(this.ShowLogItem_Click)); - this.aboutItem = CreateMenuItem(10, "About...", new System.EventHandler(this.Config_Click)); - this.SeperatorItem4 = CreateSeperatorItem(11); - this.quitItem = CreateMenuItem(12, "Quit", new System.EventHandler(this.Quit_Click)); - - // - // contextMenu1 - // + this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.enableItem, - this.modeItem, + CreateMenuGroup(1, "Mode", new System.Windows.Forms.MenuItem[] { + this.PACModeItem, + this.globalModeItem + }), this.ServersItem, - this.SeperatorItem2, + CreateSeperatorItem(3), this.AutoStartupItem, this.ShareOverLANItem, - this.editPACFileItem, - this.SeperatorItem3, - this.QRCodeItem, - this.ShowLogItem, - this.aboutItem, - this.SeperatorItem4, - this.quitItem}); + CreateMenuItem(6, "Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)), + CreateSeperatorItem(7), + CreateMenuItem(8, "Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)), + CreateMenuItem(9, "Show Logs...", new System.EventHandler(this.ShowLogItem_Click)), + CreateMenuItem(10, "About...", new System.EventHandler(this.Config_Click)), + CreateSeperatorItem(11), + CreateMenuItem(12, "Quit", new System.EventHandler(this.Quit_Click))}); } private void controller_ConfigChanged(object sender, EventArgs e) From 3f87ab6bfb5fce6aa145bb816aa1b103e986333e Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:52:41 +0800 Subject: [PATCH 18/32] lint code --- shadowsocks-csharp/View/MenuViewController.cs | 63 ++++++++++++--------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index cb40de2a..48a56f74 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -112,24 +112,25 @@ namespace Shadowsocks.View _notifyIcon.Text = text.Substring(0, Math.Min(63, text.Length)); } - private MenuItem CreateMenuItem(int index, string text, EventHandler click) + private MenuItem CreateMenuItem(string text, EventHandler click) { MenuItem result = new MenuItem(I18N.GetString(text), click); - result.Index = index; return result; } - private MenuItem CreateSeperatorItem(int index) + private MenuItem CreateSeperatorItem() { MenuItem result = new MenuItem("-"); - result.Index = index; return result; } - private MenuItem CreateMenuGroup(int index, string text, MenuItem[] items) + private MenuItem CreateMenuGroup(string text, MenuItem[] items) { + for (int i = 0; i < items.Length; i++) + { + items[i].Index = i; + } MenuItem result = new MenuItem(I18N.GetString(text), items); - result.Index = index; return result; } @@ -137,37 +138,27 @@ namespace Shadowsocks.View { this.contextMenu1 = new System.Windows.Forms.ContextMenu(); - this.PACModeItem = CreateMenuItem(0, "PAC", new System.EventHandler(this.PACModeItem_Click)); - this.globalModeItem = CreateMenuItem(1, "Global", new System.EventHandler(this.GlobalModeItem_Click)); - - this.SeperatorItem = CreateSeperatorItem(0); - this.ConfigItem = CreateMenuItem(1, "Edit Servers...", new System.EventHandler(this.Config_Click)); - - this.enableItem = CreateMenuItem(0, "Enable", new System.EventHandler(this.EnableItem_Click)); - this.ServersItem = CreateMenuGroup(2, "Servers", new System.Windows.Forms.MenuItem[] { - this.SeperatorItem, - this.ConfigItem - }); - this.AutoStartupItem = CreateMenuItem(4, "Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)); - this.ShareOverLANItem = CreateMenuItem(5, "Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)); - this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { - this.enableItem, - CreateMenuGroup(1, "Mode", new System.Windows.Forms.MenuItem[] { - this.PACModeItem, - this.globalModeItem - }), - this.ServersItem, - CreateSeperatorItem(3), - this.AutoStartupItem, - this.ShareOverLANItem, - CreateMenuItem(6, "Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)), - CreateSeperatorItem(7), - CreateMenuItem(8, "Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)), - CreateMenuItem(9, "Show Logs...", new System.EventHandler(this.ShowLogItem_Click)), - CreateMenuItem(10, "About...", new System.EventHandler(this.Config_Click)), - CreateSeperatorItem(11), - CreateMenuItem(12, "Quit", new System.EventHandler(this.Quit_Click))}); + this.enableItem = CreateMenuItem("Enable", new System.EventHandler(this.EnableItem_Click)), + CreateMenuGroup("Mode", new System.Windows.Forms.MenuItem[] { + this.PACModeItem = CreateMenuItem("PAC", new System.EventHandler(this.PACModeItem_Click)), + this.globalModeItem = CreateMenuItem("Global", new System.EventHandler(this.GlobalModeItem_Click)) + }), + this.ServersItem = CreateMenuGroup("Servers", new System.Windows.Forms.MenuItem[] { + this.SeperatorItem = CreateSeperatorItem(), + this.ConfigItem = CreateMenuItem("Edit Servers...", new System.EventHandler(this.Config_Click)) + }), + CreateSeperatorItem(), + this.AutoStartupItem = CreateMenuItem("Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)), + this.ShareOverLANItem = CreateMenuItem("Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)), + CreateMenuItem("Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)), + CreateSeperatorItem(), + CreateMenuItem("Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)), + CreateMenuItem("Show Logs...", new System.EventHandler(this.ShowLogItem_Click)), + CreateMenuItem("About...", new System.EventHandler(this.Config_Click)), + CreateSeperatorItem(), + CreateMenuItem("Quit", new System.EventHandler(this.Quit_Click)) + }); } private void controller_ConfigChanged(object sender, EventArgs e) From 3da1e7f95b6332a7f848dd918e55a29f401dc57f Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:55:00 +0800 Subject: [PATCH 19/32] clean code --- shadowsocks-csharp/View/MenuViewController.cs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 48a56f74..3010c17f 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -114,24 +114,12 @@ namespace Shadowsocks.View private MenuItem CreateMenuItem(string text, EventHandler click) { - MenuItem result = new MenuItem(I18N.GetString(text), click); - return result; - } - - private MenuItem CreateSeperatorItem() - { - MenuItem result = new MenuItem("-"); - return result; + return new MenuItem(I18N.GetString(text), click); } private MenuItem CreateMenuGroup(string text, MenuItem[] items) { - for (int i = 0; i < items.Length; i++) - { - items[i].Index = i; - } - MenuItem result = new MenuItem(I18N.GetString(text), items); - return result; + return new MenuItem(I18N.GetString(text), items); } private void LoadMenu() @@ -145,18 +133,18 @@ namespace Shadowsocks.View this.globalModeItem = CreateMenuItem("Global", new System.EventHandler(this.GlobalModeItem_Click)) }), this.ServersItem = CreateMenuGroup("Servers", new System.Windows.Forms.MenuItem[] { - this.SeperatorItem = CreateSeperatorItem(), + this.SeperatorItem = new MenuItem("-"), this.ConfigItem = CreateMenuItem("Edit Servers...", new System.EventHandler(this.Config_Click)) }), - CreateSeperatorItem(), + new MenuItem("-"), this.AutoStartupItem = CreateMenuItem("Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)), this.ShareOverLANItem = CreateMenuItem("Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)), CreateMenuItem("Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)), - CreateSeperatorItem(), + new MenuItem("-"), CreateMenuItem("Show QRCode...", new System.EventHandler(this.QRCodeItem_Click)), CreateMenuItem("Show Logs...", new System.EventHandler(this.ShowLogItem_Click)), CreateMenuItem("About...", new System.EventHandler(this.Config_Click)), - CreateSeperatorItem(), + new MenuItem("-"), CreateMenuItem("Quit", new System.EventHandler(this.Quit_Click)) }); } From 73d32b0dc774d956cdb3db2d97186e3089cf62e7 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:56:09 +0800 Subject: [PATCH 20/32] clean more --- shadowsocks-csharp/View/MenuViewController.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 3010c17f..06958eb7 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -124,9 +124,7 @@ namespace Shadowsocks.View private void LoadMenu() { - this.contextMenu1 = new System.Windows.Forms.ContextMenu(); - - this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { + this.contextMenu1 = new System.Windows.Forms.ContextMenu(new System.Windows.Forms.MenuItem[] { this.enableItem = CreateMenuItem("Enable", new System.EventHandler(this.EnableItem_Click)), CreateMenuGroup("Mode", new System.Windows.Forms.MenuItem[] { this.PACModeItem = CreateMenuItem("PAC", new System.EventHandler(this.PACModeItem_Click)), From 7002a666a7878f3d103e718fd422fe2197cdb8f1 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 22:57:17 +0800 Subject: [PATCH 21/32] clean more --- shadowsocks-csharp/View/MenuViewController.cs | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 06958eb7..b36c836b 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -124,26 +124,26 @@ namespace Shadowsocks.View private void LoadMenu() { - this.contextMenu1 = new System.Windows.Forms.ContextMenu(new System.Windows.Forms.MenuItem[] { - this.enableItem = CreateMenuItem("Enable", new System.EventHandler(this.EnableItem_Click)), - CreateMenuGroup("Mode", new System.Windows.Forms.MenuItem[] { - this.PACModeItem = CreateMenuItem("PAC", new System.EventHandler(this.PACModeItem_Click)), - this.globalModeItem = CreateMenuItem("Global", new System.EventHandler(this.GlobalModeItem_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 System.Windows.Forms.MenuItem[] { + this.ServersItem = CreateMenuGroup("Servers", new MenuItem[] { this.SeperatorItem = new MenuItem("-"), - this.ConfigItem = CreateMenuItem("Edit Servers...", new System.EventHandler(this.Config_Click)) + this.ConfigItem = CreateMenuItem("Edit Servers...", new EventHandler(this.Config_Click)) }), new MenuItem("-"), - this.AutoStartupItem = CreateMenuItem("Start on Boot", new System.EventHandler(this.AutoStartupItem_Click)), - this.ShareOverLANItem = CreateMenuItem("Share over LAN", new System.EventHandler(this.ShareOverLANItem_Click)), - CreateMenuItem("Edit PAC File...", new System.EventHandler(this.EditPACFileItem_Click)), + 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 System.EventHandler(this.QRCodeItem_Click)), - CreateMenuItem("Show Logs...", new System.EventHandler(this.ShowLogItem_Click)), - CreateMenuItem("About...", new System.EventHandler(this.Config_Click)), + CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)), + CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), + CreateMenuItem("About...", new EventHandler(this.Config_Click)), new MenuItem("-"), - CreateMenuItem("Quit", new System.EventHandler(this.Quit_Click)) + CreateMenuItem("Quit", new EventHandler(this.Quit_Click)) }); } From 604feb76d44e6ad803bafde58e448b0bf6d2df32 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Thu, 1 Jan 2015 23:53:28 +0800 Subject: [PATCH 22/32] fix about item --- shadowsocks-csharp/View/MenuViewController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index b36c836b..797e52f7 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -141,7 +141,7 @@ namespace Shadowsocks.View new MenuItem("-"), CreateMenuItem("Show QRCode...", new EventHandler(this.QRCodeItem_Click)), CreateMenuItem("Show Logs...", new EventHandler(this.ShowLogItem_Click)), - CreateMenuItem("About...", new EventHandler(this.Config_Click)), + CreateMenuItem("About...", new EventHandler(this.AboutItem_Click)), new MenuItem("-"), CreateMenuItem("Quit", new EventHandler(this.Quit_Click)) }); From 25b8ef71662f67f62c4c4b9d473e201a12c4f5c8 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Fri, 2 Jan 2015 00:20:19 +0800 Subject: [PATCH 23/32] bump --- CHANGES | 4 ++++ LICENSE.txt | 2 +- shadowsocks-csharp/Controller/UpdateChecker.cs | 2 +- shadowsocks-csharp/Properties/AssemblyInfo.cs | 2 +- test/Properties/AssemblyInfo.cs | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index de4f3199..a9554b6a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +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 diff --git a/LICENSE.txt b/LICENSE.txt index 7801cdf2..efd23769 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,7 @@ shadowsocks-csharp ================== -Copyright (C) 2014 clowwindy +Copyright (C) 2015 clowwindy 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 diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index a7683318..e71d95c9 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -17,7 +17,7 @@ namespace Shadowsocks.Controller public string LatestVersionURL; public event EventHandler NewVersionFound; - public const string Version = "2.1.5"; + public const string Version = "2.1.6"; public void CheckUpdate() { diff --git a/shadowsocks-csharp/Properties/AssemblyInfo.cs b/shadowsocks-csharp/Properties/AssemblyInfo.cs index edc36101..2a6fc3db 100755 --- a/shadowsocks-csharp/Properties/AssemblyInfo.cs +++ b/shadowsocks-csharp/Properties/AssemblyInfo.cs @@ -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("")] diff --git a/test/Properties/AssemblyInfo.cs b/test/Properties/AssemblyInfo.cs index 2918bf7a..26e77a34 100755 --- a/test/Properties/AssemblyInfo.cs +++ b/test/Properties/AssemblyInfo.cs @@ -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("")] From 0e152d56abf471ddba1bf824c20a6e63295f0ccc Mon Sep 17 00:00:00 2001 From: clowwindy Date: Fri, 2 Jan 2015 00:23:23 +0800 Subject: [PATCH 24/32] remove settings file --- shadowsocks-csharp/Properties/Settings.Designer.cs | 26 ---------------------- shadowsocks-csharp/Properties/Settings.settings | 7 ------ shadowsocks-csharp/shadowsocks-csharp.csproj | 9 -------- 3 files changed, 42 deletions(-) delete mode 100755 shadowsocks-csharp/Properties/Settings.Designer.cs delete mode 100755 shadowsocks-csharp/Properties/Settings.settings diff --git a/shadowsocks-csharp/Properties/Settings.Designer.cs b/shadowsocks-csharp/Properties/Settings.Designer.cs deleted file mode 100755 index 685146c2..00000000 --- a/shadowsocks-csharp/Properties/Settings.Designer.cs +++ /dev/null @@ -1,26 +0,0 @@ -//------------------------------------------------------------------------------ -// -// 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. -// -//------------------------------------------------------------------------------ - -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; - } - } - } -} diff --git a/shadowsocks-csharp/Properties/Settings.settings b/shadowsocks-csharp/Properties/Settings.settings deleted file mode 100755 index abf36c5d..00000000 --- a/shadowsocks-csharp/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index a7216f48..e044d4fb 100755 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -144,15 +144,6 @@ - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - From 431b638febb9ed5035ea67e77e6740785f9aa59e Mon Sep 17 00:00:00 2001 From: clowwindy Date: Fri, 2 Jan 2015 19:13:48 +0800 Subject: [PATCH 25/32] Update LICENSE.txt --- LICENSE.txt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index efd23769..0ad58243 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -81,20 +81,20 @@ 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 --------- - -QRCode for C#4.0 Silverlight is translation of QRCode for JavaScript -https://github.com/jeromeetienne/jquery-qrcode/ +ZXing +----- -Copyright (c) 2009 Kazuhiko Arase +Copyright 2007 ZXing authors -URL: http://www.d-project.com/ +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 -Licensed under the MIT license: - http://www.opensource.org/licenses/mit-license.php + http://www.apache.org/licenses/LICENSE-2.0 -The word "QR Code" is registered trademark of -DENSO WAVE INCORPORATED - http://www.denso-wave.com/qrcode/faqpatent-e.html +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. From 988bf98fedb475686fdf29ac4f9c08b62b2bb7bc Mon Sep 17 00:00:00 2001 From: clowwindy Date: Fri, 2 Jan 2015 19:15:12 +0800 Subject: [PATCH 26/32] Update LICENSE.txt --- LICENSE.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/LICENSE.txt b/LICENSE.txt index 0ad58243..c09e49f7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -98,3 +98,21 @@ 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. + +libsodium +--------- + +Copyright (c) 2013-2015 +Frank Denis + +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. From 4856b1c74a09966ff5f960a2b47009ac072c3d5e Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 6 Jan 2015 19:37:59 +0800 Subject: [PATCH 27/32] Create CONTRIBUTING.md --- CONTRIBUTING.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..6eb927af --- /dev/null +++ b/CONTRIBUTING.md @@ -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 From aa8a816f9f893de6ec878d03ac3da89b747e0bd6 Mon Sep 17 00:00:00 2001 From: clowwindy Date: Tue, 6 Jan 2015 20:13:36 +0800 Subject: [PATCH 28/32] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6eb927af..ace27628 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -How to contribute +How to Contribute ================= Pull Requests From 1d8c414c9fd6775933196c0cce0bdf1410dee878 Mon Sep 17 00:00:00 2001 From: Gang Zhuo Date: Tue, 6 Jan 2015 23:02:15 -0500 Subject: [PATCH 29/32] Bring ConfigForm to front when it's opened before. --- shadowsocks-csharp/View/MenuViewController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 797e52f7..a22a8b05 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -231,7 +231,7 @@ namespace Shadowsocks.View { if (configForm != null) { - configForm.Focus(); + configForm.Activate(); } else { From b10d06dd4b9687fc3026e16c96a0fd29c3a8e17c Mon Sep 17 00:00:00 2001 From: sin_sin Date: Wed, 7 Jan 2015 15:43:05 +0800 Subject: [PATCH 30/32] * Add logging timestamp, ref #113 --- shadowsocks-csharp/Controller/Local.cs | 1 + shadowsocks-csharp/Controller/Logging.cs | 27 +++++++++++++++++++++++++- shadowsocks-csharp/Controller/UpdateChecker.cs | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index cd6d2f96..ba507c14 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -61,6 +61,7 @@ namespace Shadowsocks.Controller public void Stop() { _listener.Close(); + // Console.WriteLine("Shadowsocks stopped"); } diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs index 22b5b9b1..208051e6 100755 --- a/shadowsocks-csharp/Controller/Logging.cs +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -18,7 +18,7 @@ namespace Shadowsocks.Controller 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 +61,30 @@ namespace Shadowsocks.Controller Console.WriteLine(e); } } + + } + + // Simply extened 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); + } } + } diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index e71d95c9..d6653468 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -145,7 +145,7 @@ namespace Shadowsocks.Controller } catch (Exception ex) { - Console.Write(ex.ToString()); + Console.WriteLine(ex.ToString()); return; } } From 8a1ea1eee4f89619b2cf79c718535fc3bd4bf2a3 Mon Sep 17 00:00:00 2001 From: sin_sin Date: Thu, 8 Jan 2015 10:29:38 +0800 Subject: [PATCH 31/32] * Clean unused tmp, fix spelling of the comment --- shadowsocks-csharp/Controller/Logging.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shadowsocks-csharp/Controller/Logging.cs b/shadowsocks-csharp/Controller/Logging.cs index 208051e6..81f16dd8 100755 --- a/shadowsocks-csharp/Controller/Logging.cs +++ b/shadowsocks-csharp/Controller/Logging.cs @@ -17,7 +17,6 @@ namespace Shadowsocks.Controller string temppath = Path.GetTempPath(); LogFile = Path.Combine(temppath, "shadowsocks.log"); FileStream fs = new FileStream(LogFile, FileMode.Append); - TextWriter tmp = Console.Out; StreamWriterWithTimestamp sw = new StreamWriterWithTimestamp(fs); sw.AutoFlush = true; Console.SetOut(sw); @@ -64,7 +63,7 @@ namespace Shadowsocks.Controller } - // Simply extened System.IO.StreamWriter for adding timestamp workaround + // Simply extended System.IO.StreamWriter for adding timestamp workaround public class StreamWriterWithTimestamp : StreamWriter { public StreamWriterWithTimestamp(Stream stream) : base(stream) From 1d21f2504df726727760bfccfab9a7e0fed2b455 Mon Sep 17 00:00:00 2001 From: sin_sin Date: Thu, 8 Jan 2015 15:10:26 +0800 Subject: [PATCH 32/32] * Remove stop event log --- shadowsocks-csharp/Controller/Local.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/shadowsocks-csharp/Controller/Local.cs b/shadowsocks-csharp/Controller/Local.cs index ba507c14..cd6d2f96 100755 --- a/shadowsocks-csharp/Controller/Local.cs +++ b/shadowsocks-csharp/Controller/Local.cs @@ -61,7 +61,6 @@ namespace Shadowsocks.Controller public void Stop() { _listener.Close(); - // Console.WriteLine("Shadowsocks stopped"); }