1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 // (c) 2008-2011 Moz (@syo68k)
4 // (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 // (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 // (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 // (c) 2011 Egtra (@egtra) <http://dev.activebasic.com/egtra/>
8 // (c) 2011 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
9 // All rights reserved.
11 // This file is part of OpenTween.
13 // This program is free software; you can redistribute it and/or modify it
14 // under the terms of the GNU General public License as published by the Free
15 // Software Foundation; either version 3 of the License, or (at your option)
18 // This program is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General public License
23 // You should have received a copy of the GNU General public License along
24 // with this program. if not, see <http://www.gnu.org/licenses/>, or write to
25 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
26 // Boston, MA 02110-1301, USA.
29 using System.Collections.Generic;
33 using System.Windows.Forms;
35 using System.Globalization;
36 using System.Security.Cryptography;
38 using System.Drawing.Imaging;
39 using System.Collections;
40 using System.Security.Principal;
41 using System.Runtime.Serialization.Json;
42 using System.Reflection;
43 using System.Diagnostics;
44 using System.Text.RegularExpressions;
45 using System.Net.NetworkInformation;
49 [Microsoft.VisualBasic.CompilerServices.StandardModule]
50 public sealed class MyCommon
52 private static readonly object LockObj = new object();
53 public static bool _endingFlag; //終了フラグ
54 public static string cultureStr = null;
55 public static string settingPath;
66 public enum NameBalloonEnum
73 public enum DispTitleEnum
85 public enum LogUnitEnum
92 public enum UploadFileType
99 public enum UrlConverter
113 public enum OutputzUrlmode
116 twittercomWithUsername,
119 public enum HITRESULT
128 public enum HttpTimeOut
135 //Backgroundworkerへ処理種別を通知するための引数用enum
136 public enum WORKERTYPE
140 DirectMessegeRcv, //受信DM取得
141 DirectMessegeSnt, //送信DM取得
142 PostMessage, //発言POST
145 Follower, //Followerリスト取得
152 UserStream, //UserStream
153 UserTimeline, //UserTimeline
154 BlockIds, //Blocking/ids
155 Configuration, //Twitter Configuration読み込み
157 ErrorState, //エラー表示のみで後処理終了(認証エラー時など)
160 public static class DEFAULTTAB
162 public const string RECENT = "Recent";
163 public const string REPLY = "Reply";
164 public const string DM = "Direct";
165 public const string FAV = "Favorites";
167 //private string dummy;
169 //private object ReferenceEquals()
171 // return new object();
173 //private object Equals()
175 // return new object();
179 public static readonly object Block = null;
180 public static bool TraceFlag = false;
183 public static bool DebugBuild = true;
185 public static bool DebugBuild = false;
188 public enum ACCOUNT_STATE
194 public enum REPLY_ICONSTATE
202 public enum EVENTTYPE
209 ListMemberRemoved = 16,
217 All = (None | Favorite | Unfavorite | Follow | ListMemberAdded | ListMemberRemoved |
218 Block | Unblock | UserUpdate | Deleted | ListCreated | ListUpdated),
221 public static void TraceOut(Exception ex, string Message)
223 var buf = ExceptionOutMessage(ex);
224 TraceOut(TraceFlag, Message + Environment.NewLine + buf);
227 public static void TraceOut(string Message)
229 TraceOut(TraceFlag, Message);
232 public static void TraceOut(bool OutputFlag, string Message)
236 if (!OutputFlag) return;
237 var now = DateTime.Now;
238 var fileName = string.Format("{0}Trace-{1:0000}{2:00}{3:00}-{4:00}{5:00}{6:00}.log", GetAssemblyName(), now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);
240 using (var writer = new StreamWriter(fileName))
242 writer.WriteLine("**** TraceOut: {0} ****", DateTime.Now.ToString());
243 writer.WriteLine(Properties.Resources.TraceOutText1);
244 writer.WriteLine(Properties.Resources.TraceOutText2);
246 writer.WriteLine(Properties.Resources.TraceOutText3);
247 writer.WriteLine(Properties.Resources.TraceOutText4, Environment.OSVersion.VersionString);
248 writer.WriteLine(Properties.Resources.TraceOutText5, Environment.Version.ToString());
249 writer.WriteLine(Properties.Resources.TraceOutText6, fileVersion);
250 writer.WriteLine(Message);
257 // 注意:最終的にファイル出力されるエラーログに記録されるため次の情報は書き出さない
259 // Dataプロパティにある終了許可フラグのパースもここで行う
261 public static string ExceptionOutMessage(Exception ex)
263 bool IsTerminatePermission = true;
264 return ExceptionOutMessage(ex, ref IsTerminatePermission);
267 public static string ExceptionOutMessage(Exception ex, ref bool IsTerminatePermission)
269 if (ex == null) return "";
271 var buf = new StringBuilder();
273 buf.AppendFormat(Properties.Resources.UnhandledExceptionText8, ex.GetType().FullName, ex.Message);
277 var needHeader = true;
278 foreach (DictionaryEntry dt in ex.Data)
283 buf.AppendLine("-------Extra Information-------");
286 buf.AppendFormat("{0} : {1}", dt.Key, dt.Value);
288 if (dt.Key.Equals("IsTerminatePermission"))
290 IsTerminatePermission = (bool)dt.Value;
295 buf.AppendLine("-----End Extra Information-----");
298 buf.AppendLine(ex.StackTrace);
301 //InnerExceptionが存在する場合書き出す
302 var _ex = ex.InnerException;
306 buf.AppendFormat("-----InnerException[{0}]-----\r\n", nesting);
308 buf.AppendFormat(Properties.Resources.UnhandledExceptionText8, _ex.GetType().FullName, _ex.Message);
310 if (_ex.Data != null)
312 var needHeader = true;
314 foreach (DictionaryEntry dt in _ex.Data)
319 buf.AppendLine("-------Extra Information-------");
322 buf.AppendFormat("{0} : {1}", dt.Key, dt.Value);
323 if (dt.Key.Equals("IsTerminatePermission"))
325 IsTerminatePermission = (bool)dt.Value;
330 buf.AppendLine("-----End Extra Information-----");
333 buf.AppendLine(_ex.StackTrace);
336 _ex = _ex.InnerException;
338 return buf.ToString();
341 public static bool ExceptionOut(Exception ex)
345 var IsTerminatePermission = true;
346 var now = DateTime.Now;
347 var fileName = string.Format("{0}-{1:0000}{2:00}{3:00}-{4:00}{5:00}{6:00}.log", GetAssemblyName(), now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);
349 using (var writer = new StreamWriter(fileName))
351 var ident = WindowsIdentity.GetCurrent();
352 var princ = new WindowsPrincipal(ident);
354 writer.WriteLine(Properties.Resources.UnhandledExceptionText1, DateTime.Now.ToString());
355 writer.WriteLine(Properties.Resources.UnhandledExceptionText2);
356 writer.WriteLine(Properties.Resources.UnhandledExceptionText3);
358 writer.WriteLine(Properties.Resources.UnhandledExceptionText11 + princ.IsInRole(WindowsBuiltInRole.Administrator).ToString());
359 writer.WriteLine(Properties.Resources.UnhandledExceptionText12 + princ.IsInRole(WindowsBuiltInRole.User).ToString());
361 // OSVersion,AppVersion書き出し
362 writer.WriteLine(Properties.Resources.UnhandledExceptionText4);
363 writer.WriteLine(Properties.Resources.UnhandledExceptionText5, Environment.OSVersion.VersionString);
364 writer.WriteLine(Properties.Resources.UnhandledExceptionText6, Environment.Version.ToString());
365 writer.WriteLine(Properties.Resources.UnhandledExceptionText7, fileVersion);
367 writer.Write(ExceptionOutMessage(ex, ref IsTerminatePermission));
371 switch (MessageBox.Show(string.Format(Properties.Resources.UnhandledExceptionText9, fileName, Environment.NewLine),
372 Properties.Resources.UnhandledExceptionText10, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Error))
374 case DialogResult.Yes:
375 Process.Start(fileName);
377 case DialogResult.No:
379 case DialogResult.Cancel:
380 return IsTerminatePermission;
382 throw new Exception("");
388 /// URLに含まれているマルチバイト文字列を%xx形式でエンコードします。
390 /// マルチバイト文字のコードはUTF-8またはUnicodeで自動的に判断します。
393 /// <param name = input>エンコード対象のURL</param>
394 /// <returns>マルチバイト文字の部分をUTF-8/%xx形式でエンコードした文字列を返します。</returns>
396 public static string urlEncodeMultibyteChar(string _input)
399 var sb = new StringBuilder(256);
402 foreach (var c in _input)
405 if (Convert.ToInt32(c) > 127) break;
407 if (Convert.ToInt32(c_) <= 127) return _input;
409 var input = HttpUtility.UrlDecode(_input);
411 foreach (char c in input)
413 if (Convert.ToInt32(c) > 255)
415 // Unicodeの場合(1charが複数のバイトで構成されている)
416 // Uriクラスをnewして再構成し、入力をPathAndQueryのみとしてやり直す
417 foreach (var b in Encoding.UTF8.GetBytes(c.ToString()))
419 sb.AppendFormat("%{0:X2}", b);
422 else if (Convert.ToInt32(c) > 127 || c == '%')
425 // Uriクラスをnewして再構成し、入力をinputからAuthority部分を除去してやり直す
428 uri = new Uri(input);
429 input = input.Remove(0, uri.GetLeftPart(UriPartial.Authority).Length);
435 sb.Append("%" + Convert.ToInt16(c).ToString("X2").ToUpper());
446 result = sb.ToString();
450 result = uri.GetLeftPart(UriPartial.Authority) + sb.ToString();
457 ////// URLのドメイン名をPunycode展開します。
459 ////// ドメイン名がIDNでない場合はそのまま返します。
460 ////// ドメインラベルの区切り文字はFULLSTOP(.、U002E)に置き換えられます。
463 ////// <param name="input">展開対象のURL</param>
464 ////// <returns>IDNが含まれていた場合はPunycodeに展開したURLをを返します。Punycode展開時にエラーが発生した場合はnullを返します。</returns>
466 public static string IDNDecode(string input)
469 var IDNConverter = new IdnMapping();
471 if (!input.Contains("://")) return null;
479 Domain = input.Split('/')[2];
480 AsciiDomain = IDNConverter.GetAscii(Domain);
487 return input.Replace("://" + Domain, "://" + AsciiDomain);
490 public static void MoveArrayItem(int[] values, int idx_fr, int idx_to)
492 var moved_value = values[idx_fr];
493 var num_moved = Math.Abs(idx_fr - idx_to);
497 Array.Copy(values, idx_to, values,
498 idx_to + 1, num_moved);
502 Array.Copy(values, idx_fr + 1, values,
506 values[idx_to] = moved_value;
509 public static string EncryptString(string str)
511 if (string.IsNullOrEmpty(str)) return "";
514 var bytesIn = Encoding.UTF8.GetBytes(str);
516 //DESCryptoServiceProviderオブジェクトの作成
517 using (var des = new DESCryptoServiceProvider())
521 var bytesKey = Encoding.UTF8.GetBytes("_tween_encrypt_key_");
523 des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
524 des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
526 //暗号化されたデータを書き出すためのMemoryStream
527 using (var msOut = new MemoryStream())
530 using (var desdecrypt = des.CreateEncryptor())
532 //書き込むためのCryptoStreamの作成
533 using (var cryptStream = new System.Security.Cryptography.CryptoStream(
535 CryptoStreamMode.Write))
538 cryptStream.Write(bytesIn, 0, bytesIn.Length);
539 cryptStream.FlushFinalBlock();
541 var bytesOut = msOut.ToArray();
547 //Base64で文字列に変更して結果を返す
548 return Convert.ToBase64String(bytesOut);
555 public static string DecryptString(string str)
557 if (string.IsNullOrEmpty(str)) return "";
559 //DESCryptoServiceProviderオブジェクトの作成
560 using (var des = new System.Security.Cryptography.DESCryptoServiceProvider())
564 var bytesKey = Encoding.UTF8.GetBytes("_tween_encrypt_key_");
566 des.Key = ResizeBytesArray(bytesKey, des.Key.Length);
567 des.IV = ResizeBytesArray(bytesKey, des.IV.Length);
569 //Base64で文字列をバイト配列に戻す
570 var bytesIn = Convert.FromBase64String(str);
571 //暗号化されたデータを読み込むためのMemoryStream
572 using (var msIn = new MemoryStream(bytesIn))
575 using (var desdecrypt = des.CreateDecryptor())
577 //読み込むためのCryptoStreamの作成
578 using (var cryptStreem = new CryptoStream(
580 CryptoStreamMode.Read))
582 //復号化されたデータを取得するためのStreamReader
583 using (var srOut = new StreamReader(
584 cryptStreem, Encoding.UTF8))
587 var result = srOut.ReadToEnd();
602 public static byte[] ResizeBytesArray(byte[] bytes,
605 var newBytes = new byte[newSize];
606 if (bytes.Length <= newSize)
608 foreach (var i in Enumerable.Range(0, bytes.Length))
610 newBytes[i] = bytes[i];
616 foreach (var i in Enumerable.Range(0, bytes.Length))
618 newBytes[pos] = unchecked((byte)(newBytes[pos] ^ bytes[i]));
620 if (pos >= newBytes.Length)
629 public static bool IsNT6()
632 return Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major == 6;
636 public enum TabUsageType
640 Mentions = 2, //Unique
641 DirectMessage = 4, //Unique
642 Favorites = 8, //Unique
644 LocalQuery = 32, //Pin(no save/no save query/distribute/no update(normal update))
645 Profile = 64, //Pin(save/no distribute/manual update)
646 PublicSearch = 128, //Pin(save/no distribute/auto update)
655 public static string fileVersion = "";
657 public static string GetUserAgentString()
659 if (string.IsNullOrEmpty(fileVersion))
661 throw new Exception("fileversion is not Initialized.");
663 return GetAssemblyName() + "/" + fileVersion;
666 public static ApiInformation TwitterApiInfo = new ApiInformation();
668 public static bool IsAnimatedGif(string filename)
673 img = Image.FromFile(filename);
674 if (img == null) return false;
675 if (img.RawFormat.Guid == ImageFormat.Gif.Guid)
677 var fd = new FrameDimension(img.FrameDimensionsList[0]);
678 var fd_count = img.GetFrameCount(fd);
696 if (img != null) img.Dispose();
700 public static DateTime DateTimeParse(string input)
704 "ddd MMM dd HH:mm:ss zzzz yyyy",
706 foreach (var fmt in format)
708 if (DateTime.TryParseExact(input,
710 DateTimeFormatInfo.InvariantInfo,
721 TraceOut("Parse Error(DateTimeFormat) : " + input);
722 return new DateTime();
725 public static T CreateDataFromJson<T>(string content)
728 using (var stream = new MemoryStream())
730 var buf = Encoding.Unicode.GetBytes(content);
731 stream.Write(Encoding.Unicode.GetBytes(content), offset: 0, count: buf.Length);
732 stream.Seek(offset: 0, loc: SeekOrigin.Begin);
733 data = (T)((new DataContractJsonSerializer(typeof(T))).ReadObject(stream));
738 public static bool IsNetworkAvailable()
742 return NetworkInterface.GetIsNetworkAvailable();
750 static bool IsValidEmail(string strIn)
752 // Return true if strIn is in valid e-mail format.
753 return Regex.IsMatch(strIn,
754 @"^(?("")("".+?""@)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])@))" +
755 @"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$");
759 /// 指定された修飾キーが押されている状態かを取得します。
761 /// <param name="keys">状態を調べるキー</param>
762 /// <returns><paramref name="keys"/> で指定された修飾キーがすべて押されている状態であれば true。それ以外であれば false。</returns>
763 public static bool IsKeyDown(params Keys[] keys)
765 foreach (Keys key in keys)
767 if ((Control.ModifierKeys & key) != key)
776 /// アプリケーションのアセンブリ名を取得します。
779 /// VB.NETの<code>My.Application.Info.AssemblyName</code>と(ほぼ)同じ動作をします。
781 /// <returns>アプリケーションのアセンブリ名</returns>
782 public static string GetAssemblyName()
784 return Assembly.GetEntryAssembly().GetName().Name;