1 ' Tween - 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>
9 ' This file is part of Tween.
11 ' This program is free software; you can redistribute it and/or modify it
12 ' under the terms of the GNU General Public License as published by the Free
13 ' Software Foundation; either version 3 of the License, or (at your option)
16 ' This program is distributed in the hope that it will be useful, but
17 ' WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 ' or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 ' You should have received a copy of the GNU General Public License along
22 ' with this program. If not, see <http://www.gnu.org/licenses/>, or write to
23 ' the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
24 ' Boston, MA 02110-1301, USA.
27 Imports System.Globalization
28 Imports System.Security.Principal
29 Imports System.Reflection
32 Imports System.Runtime.Serialization.Json
34 Public Module MyCommon
35 Private ReadOnly LockObj As New Object
36 Public _endingFlag As Boolean '終了フラグ
37 Public cultureStr As String = Nothing
47 Public Enum NameBalloonEnum
53 Public Enum DispTitleEnum
64 Public Enum LogUnitEnum
70 Public Enum UploadFileType
76 Public Enum UrlConverter
89 Public Enum OutputzUrlmode
91 twittercomWithUsername
102 Public Enum HttpTimeOut
108 'Backgroundworkerへ処理種別を通知するための引数用Enum
109 Public Enum WORKERTYPE
112 DirectMessegeRcv '受信DM取得
113 DirectMessegeSnt '送信DM取得
117 Follower 'Followerリスト取得
124 UserStream 'UserStream
125 UserTimeline 'UserTimeline
126 BlockIds 'Blocking/ids
128 ErrorState 'エラー表示のみで後処理終了(認証エラー時など)
131 Public Structure DEFAULTTAB
132 Const RECENT As String = "Recent"
133 Const REPLY As String = "Reply"
134 Const DM As String = "Direct"
135 Const FAV As String = "Favorites"
137 Private dummy As String
139 Private Shadows Function ReferenceEquals() As Object
142 Private Shadows Function Equals() As Object
147 Public Const Block As Object = Nothing
148 Public TraceFlag As Boolean = False
151 Public DebugBuild As Boolean = True
153 Public DebugBuild As Boolean = False
156 Public Enum ACCOUNT_STATE
162 Public Enum REPLY_ICONSTATE
169 Public Enum EVENTTYPE
175 ListMemberRemoved = 16
183 All = (None Or Favorite Or Unfavorite Or Follow Or ListMemberAdded Or ListMemberRemoved Or _
184 Block Or Unblock Or UserUpdate Or Deleted Or ListCreated Or ListUpdated)
187 Public Sub TraceOut(ByVal ex As Exception, ByVal Message As String)
188 Dim buf As String = ExceptionOutMessage(ex)
189 TraceOut(TraceFlag, Message + Environment.NewLine + buf)
192 Public Sub TraceOut(ByVal Message As String)
193 TraceOut(TraceFlag, Message)
196 Public Sub TraceOut(ByVal OutputFlag As Boolean, ByVal Message As String)
198 If Not OutputFlag Then Exit Sub
199 Dim now As DateTime = DateTime.Now
200 Dim fileName As String = String.Format("TweenTrace-{0:0000}{1:00}{2:00}-{3:00}{4:00}{5:00}.log", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second)
202 Using writer As IO.StreamWriter = New IO.StreamWriter(fileName)
203 writer.WriteLine("**** TraceOut: {0} ****", DateTime.Now.ToString())
204 writer.WriteLine(My.Resources.TraceOutText1)
205 writer.WriteLine(My.Resources.TraceOutText2)
207 writer.WriteLine(My.Resources.TraceOutText3)
208 writer.WriteLine(My.Resources.TraceOutText4, Environment.OSVersion.VersionString)
209 writer.WriteLine(My.Resources.TraceOutText5, Environment.Version.ToString())
210 writer.WriteLine(My.Resources.TraceOutText6, fileVersion)
211 writer.WriteLine(Message)
218 ' 注意:最終的にファイル出力されるエラーログに記録されるため次の情報は書き出さない
220 ' Dataプロパティにある終了許可フラグのパースもここで行う
222 Public Function ExceptionOutMessage(ByVal ex As Exception, _
223 Optional ByRef IsTerminatePermission As Boolean = True) As String
224 If ex Is Nothing Then Return ""
226 Dim buf As New StringBuilder
228 buf.AppendFormat(My.Resources.UnhandledExceptionText8, ex.GetType().FullName, ex.Message)
230 If ex.Data IsNot Nothing Then
231 Dim needHeader As Boolean = True
232 For Each dt As DictionaryEntry In ex.Data
235 buf.AppendLine("-------Extra Information-------")
238 buf.AppendFormat("{0} : {1}", dt.Key, dt.Value)
240 If dt.Key.Equals("IsTerminatePermission") Then
241 IsTerminatePermission = CBool(dt.Value)
244 If Not needHeader Then
245 buf.AppendLine("-----End Extra Information-----")
248 buf.AppendLine(ex.StackTrace)
251 'InnerExceptionが存在する場合書き出す
252 Dim _ex As Exception = ex.InnerException
253 Dim nesting As Integer = 0
254 While _ex IsNot Nothing
255 buf.AppendFormat("-----InnerException[{0}]-----" + vbCrLf, nesting)
257 buf.AppendFormat(My.Resources.UnhandledExceptionText8, _ex.GetType().FullName, _ex.Message)
259 If _ex.Data IsNot Nothing Then
260 Dim needHeader As Boolean = True
262 For Each dt As DictionaryEntry In _ex.Data
265 buf.AppendLine("-------Extra Information-------")
268 buf.AppendFormat("{0} : {1}", dt.Key, dt.Value)
269 If dt.Key.Equals("IsTerminatePermission") Then
270 IsTerminatePermission = CBool(dt.Value)
273 If Not needHeader Then
274 buf.AppendLine("-----End Extra Information-----")
277 buf.AppendLine(_ex.StackTrace)
280 _ex = _ex.InnerException
282 Return buf.ToString()
285 Public Function ExceptionOut(ByVal ex As Exception) As Boolean
287 Dim IsTerminatePermission As Boolean = True
288 Dim now As DateTime = DateTime.Now
289 Dim fileName As String = String.Format("Tween-{0:0000}{1:00}{2:00}-{3:00}{4:00}{5:00}.log", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second)
291 Using writer As IO.StreamWriter = New IO.StreamWriter(fileName)
292 Dim ident As WindowsIdentity = WindowsIdentity.GetCurrent()
293 Dim princ As New WindowsPrincipal(ident)
295 writer.WriteLine(My.Resources.UnhandledExceptionText1, DateTime.Now.ToString())
296 writer.WriteLine(My.Resources.UnhandledExceptionText2)
297 writer.WriteLine(My.Resources.UnhandledExceptionText3)
299 writer.WriteLine(My.Resources.UnhandledExceptionText11 + princ.IsInRole(WindowsBuiltInRole.Administrator).ToString)
300 writer.WriteLine(My.Resources.UnhandledExceptionText12 + princ.IsInRole(WindowsBuiltInRole.User).ToString)
302 ' OSVersion,AppVersion書き出し
303 writer.WriteLine(My.Resources.UnhandledExceptionText4)
304 writer.WriteLine(My.Resources.UnhandledExceptionText5, Environment.OSVersion.VersionString)
305 writer.WriteLine(My.Resources.UnhandledExceptionText6, Environment.Version.ToString())
306 writer.WriteLine(My.Resources.UnhandledExceptionText7, fileVersion)
308 writer.Write(ExceptionOutMessage(ex, IsTerminatePermission))
312 Select Case MessageBox.Show(String.Format(My.Resources.UnhandledExceptionText9, fileName, Environment.NewLine), _
313 My.Resources.UnhandledExceptionText10, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Error)
314 Case DialogResult.Yes
315 Diagnostics.Process.Start(fileName)
319 Case DialogResult.Cancel
320 Return IsTerminatePermission
326 ''' URLに含まれているマルチバイト文字列を%xx形式でエンコードします。
328 ''' マルチバイト文字のコードはUTF-8またはUnicodeで自動的に判断します。
331 ''' <param name = input>エンコード対象のURL</param>
332 ''' <returns>マルチバイト文字の部分をUTF-8/%xx形式でエンコードした文字列を返します。</returns>
334 Public Function urlEncodeMultibyteChar(ByVal _input As String) As String
335 Dim uri As Uri = Nothing
336 Dim sb As StringBuilder = New StringBuilder(256)
337 Dim result As String = ""
340 If Convert.ToInt32(c) > 127 Then Exit For
342 If Convert.ToInt32(c) <= 127 Then Return _input
344 Dim input As String = HttpUtility.UrlDecode(_input)
347 If Convert.ToInt32(c) > 255 Then
348 ' Unicodeの場合(1charが複数のバイトで構成されている)
349 ' UriクラスをNewして再構成し、入力をPathAndQueryのみとしてやり直す
350 If uri Is Nothing Then
352 input = uri.PathAndQuery
356 ElseIf Convert.ToInt32(c) > 127 Then
358 ' UriクラスをNewして再構成し、入力をinputからAuthority部分を除去してやり直す
359 If uri Is Nothing Then
361 input = input.Remove(0, uri.GetLeftPart(UriPartial.Authority).Length)
365 sb.Append("%" + Convert.ToInt16(c).ToString("X2").ToUpper())
372 If uri Is Nothing Then
373 result = sb.ToString()
375 result = uri.GetLeftPart(UriPartial.Authority) + sb.ToString()
382 ''' URLのドメイン名をPunycode展開します。
384 ''' ドメイン名がIDNでない場合はそのまま返します。
385 ''' ドメインラベルの区切り文字はFULLSTOP(.、U002E)に置き換えられます。
388 ''' <param name="input">展開対象のURL</param>
389 ''' <returns>IDNが含まれていた場合はPunycodeに展開したURLをを返します。Punycode展開時にエラーが発生した場合はNothingを返します。</returns>
391 Public Function IDNDecode(ByVal input As String) As String
392 Dim result As String = ""
393 Dim IDNConverter As New IdnMapping
395 If Not input.Contains("://") Then Return Nothing
399 Dim AsciiDomain As String
402 Domain = input.Split("/"c)(2)
403 AsciiDomain = IDNConverter.GetAscii(Domain)
404 Catch ex As Exception
408 Return input.Replace("://" + Domain, "://" + AsciiDomain)
411 Public Sub MoveArrayItem(ByVal values() As Integer, ByVal idx_fr As Integer, ByVal idx_to As Integer)
412 Dim moved_value As Integer = values(idx_fr)
413 Dim num_moved As Integer = Math.Abs(idx_fr - idx_to)
415 If idx_to < idx_fr Then
416 Array.Copy(values, idx_to, values, _
417 idx_to + 1, num_moved)
419 Array.Copy(values, idx_fr + 1, values, _
423 values(idx_to) = moved_value
426 Public Function EncryptString(ByVal str As String) As String
427 If String.IsNullOrEmpty(str) Then Return ""
430 Dim bytesIn As Byte() = System.Text.Encoding.UTF8.GetBytes(str)
432 'DESCryptoServiceProviderオブジェクトの作成
433 Using des As New System.Security.Cryptography.DESCryptoServiceProvider
437 Dim bytesKey As Byte() = System.Text.Encoding.UTF8.GetBytes("_tween_encrypt_key_")
439 des.Key = ResizeBytesArray(bytesKey, des.Key.Length)
440 des.IV = ResizeBytesArray(bytesKey, des.IV.Length)
442 '暗号化されたデータを書き出すためのMemoryStream
443 Using msOut As New System.IO.MemoryStream
445 Using desdecrypt As System.Security.Cryptography.ICryptoTransform = _
446 des.CreateEncryptor()
448 '書き込むためのCryptoStreamの作成
449 Using cryptStream As New System.Security.Cryptography.CryptoStream( _
451 System.Security.Cryptography.CryptoStreamMode.Write)
453 cryptStream.Write(bytesIn, 0, bytesIn.Length)
454 cryptStream.FlushFinalBlock()
456 Dim bytesOut As Byte() = msOut.ToArray()
462 'Base64で文字列に変更して結果を返す
463 Return System.Convert.ToBase64String(bytesOut)
470 Public Function DecryptString(ByVal str As String) As String
471 If String.IsNullOrEmpty(str) Then Return ""
473 'DESCryptoServiceProviderオブジェクトの作成
474 Using des As New System.Security.Cryptography.DESCryptoServiceProvider
478 Dim bytesKey As Byte() = System.Text.Encoding.UTF8.GetBytes("_tween_encrypt_key_")
480 des.Key = ResizeBytesArray(bytesKey, des.Key.Length)
481 des.IV = ResizeBytesArray(bytesKey, des.IV.Length)
484 Dim bytesIn As Byte() = System.Convert.FromBase64String(str)
485 '暗号化されたデータを読み込むためのMemoryStream
486 Using msIn As New System.IO.MemoryStream(bytesIn)
488 Using desdecrypt As System.Security.Cryptography.ICryptoTransform = _
489 des.CreateDecryptor()
490 '読み込むためのCryptoStreamの作成
491 Using cryptStreem As New System.Security.Cryptography.CryptoStream( _
493 System.Security.Cryptography.CryptoStreamMode.Read)
495 '復号化されたデータを取得するためのStreamReader
496 Using srOut As New System.IO.StreamReader( _
497 cryptStreem, System.Text.Encoding.UTF8)
499 Dim result As String = srOut.ReadToEnd()
514 Public Function ResizeBytesArray(ByVal bytes() As Byte, _
515 ByVal newSize As Integer) As Byte()
516 Dim newBytes(newSize - 1) As Byte
517 If bytes.Length <= newSize Then
519 For i = 0 To bytes.Length - 1
520 newBytes(i) = bytes(i)
523 Dim pos As Integer = 0
525 For i = 0 To bytes.Length - 1
526 newBytes(pos) = newBytes(pos) Xor bytes(i)
528 If pos >= newBytes.Length Then
536 Public Function IsNT6() As Boolean
538 Return Environment.OSVersion.Platform = PlatformID.Win32NT AndAlso Environment.OSVersion.Version.Major = 6
542 Public Enum TabUsageType
546 DirectMessage = 4 'Unique
547 Favorites = 8 'Unique
549 LocalQuery = 32 'Pin(no save/no save query/distribute/no update(normal update))
550 Profile = 64 'Pin(save/no distribute/manual update)
551 PublicSearch = 128 'Pin(save/no distribute/auto update)
560 Public fileVersion As String = ""
562 Public Function GetUserAgentString() As String
563 If String.IsNullOrEmpty(fileVersion) Then
564 Throw New Exception("fileversion is not Initialized.")
566 Return "Tween/" + fileVersion
569 Public WithEvents TwitterApiInfo As New ApiInformation
571 Public Function IsAnimatedGif(ByVal filename As String) As Boolean
572 Dim img As Image = Nothing
574 img = Image.FromFile(filename)
575 If img Is Nothing Then Return False
576 If img.RawFormat.Guid = Imaging.ImageFormat.Gif.Guid Then
577 Dim fd As New System.Drawing.Imaging.FrameDimension(img.FrameDimensionsList(0))
578 Dim fd_count As Integer = img.GetFrameCount(fd)
587 Catch ex As Exception
590 If img IsNot Nothing Then img.Dispose()
594 Public Function DateTimeParse(ByVal input As String) As Date
596 Dim format() As String = {
597 "ddd MMM dd HH:mm:ss zzzz yyyy"
599 For Each fmt As String In format
600 If DateTime.TryParseExact(input, _
602 System.Globalization.DateTimeFormatInfo.InvariantInfo, _
603 System.Globalization.DateTimeStyles.None, _
610 TraceOut("Parse Error(DateTimeFormat) : " + input)
614 Public Function CreateDataFromJson(Of T)(ByVal content As String) As T
616 Using stream As New MemoryStream()
617 Dim buf As Byte() = Encoding.Unicode.GetBytes(content)
618 stream.Write(Encoding.Unicode.GetBytes(content), offset:=0, count:=buf.Length)
619 stream.Seek(offset:=0, loc:=SeekOrigin.Begin)
620 data = DirectCast((New DataContractJsonSerializer(GetType(T))).ReadObject(stream), T)