System.Data.SQLite

Check-in [cf55a3e9b9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cf55a3e9b93bb0b51b6d7a5551b3107bfa2c09b5
User & Date: mistachkin 2012-10-18 16:51:21.151
Context
2012-10-19
20:30
Fix typo in comment. check-in: 316547450c user: mistachkin tags: trunk
2012-10-18
16:51
Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library. check-in: cf55a3e9b9 user: mistachkin tags: trunk
2012-10-16
18:57
Update Eagle script library in externals. Also, add explicit thread cleanup to the stress test. check-in: 4d797d64ec user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to Doc/Extra/version.html.
63
64
65
66
67
68
69

70
71
72
73
74
75
76
      <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
      <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
      <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
      <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for <a href="http://system.data.sqlite.org/index.html/info/dd45aba387">[dd45aba387]</a>.</li>

      <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
      <li>Add test automation for the Windows CE binaries.</li>
    </ul>
    <p><b>1.0.82.0 - September 3, 2012</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li>
      <li>Properly handle quoted data source values in the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/8c3bee31c8">[8c3bee31c8]</a>.</li>







>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
      <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
      <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
      <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
      <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
      <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for <a href="http://system.data.sqlite.org/index.html/info/dd45aba387">[dd45aba387]</a>.</li>
      <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
      <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
      <li>Add test automation for the Windows CE binaries.</li>
    </ul>
    <p><b>1.0.82.0 - September 3, 2012</b></p>
    <ul>
      <li>Updated to <a href="http://www.sqlite.org/releaselog/3_7_14.html">SQLite 3.7.14</a>.</li>
      <li>Properly handle quoted data source values in the connection string. Fix for <a href="http://system.data.sqlite.org/index.html/info/8c3bee31c8">[8c3bee31c8]</a>.</li>
Changes to System.Data.SQLite/SQLite3.cs.
170
171
172
173
174
175
176








177
178
179
180
181
182
183
    internal override string Version
    {
      get
      {
        return SQLite3.SQLiteVersion;
      }
    }









    internal static string DefineConstants
    {
        get
        {
            StringBuilder result = new StringBuilder();
            IList<string> list = SQLiteDefineConstants.OptionList;







>
>
>
>
>
>
>
>







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    internal override string Version
    {
      get
      {
        return SQLite3.SQLiteVersion;
      }
    }

    internal override int VersionNumber
    {
      get
      {
        return SQLite3.SQLiteVersionNumber;
      }
    }

    internal static string DefineConstants
    {
        get
        {
            StringBuilder result = new StringBuilder();
            IList<string> list = SQLiteDefineConstants.OptionList;
203
204
205
206
207
208
209








210
211
212
213
214
215
216
    internal static string SQLiteVersion
    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1);
      }
    }









    internal static string SQLiteSourceId
    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1);
      }







>
>
>
>
>
>
>
>







211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
    internal static string SQLiteVersion
    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_libversion(), -1);
      }
    }

    internal static int SQLiteVersionNumber
    {
      get
      {
        return UnsafeNativeMethods.sqlite3_libversion_number();
      }
    }

    internal static string SQLiteSourceId
    {
      get
      {
        return UTF8ToString(UnsafeNativeMethods.sqlite3_sourceid(), -1);
      }
Changes to System.Data.SQLite/SQLiteBase.cs.
22
23
24
25
26
27
28




29
30
31
32
33
34
35
    internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind) { }

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }




    /// <summary>
    /// Returns the rowid of the most recent successful INSERT into the database from this connection.
    /// </summary>
    internal abstract long LastInsertRowId { get; }
    /// <summary>
    /// Returns the number of changes the last executing insert/update caused.
    /// </summary>







>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    internal SQLiteBase(SQLiteDateFormats fmt, DateTimeKind kind)
      : base(fmt, kind) { }

    /// <summary>
    /// Returns a string representing the active version of SQLite
    /// </summary>
    internal abstract string Version { get; }
    /// <summary>
    /// Returns an integer representing the active version of SQLite
    /// </summary>
    internal abstract int VersionNumber { get; }
    /// <summary>
    /// Returns the rowid of the most recent successful INSERT into the database from this connection.
    /// </summary>
    internal abstract long LastInsertRowId { get; }
    /// <summary>
    /// Returns the number of changes the last executing insert/update caused.
    /// </summary>
573
574
575
576
577
578
579
580
581
582


583







584
585
586

587






588
589

590


591

592
593
594
595
596
597
598
#else
            lock (hdl)
#endif
            {
#if !SQLITE_STANDARD
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db);
#else
                ResetConnection(hdl, db);

                SQLiteErrorCode n;










                try
                {
                    n = UnsafeNativeMethods.sqlite3_close_v2(db);

                }






                catch (EntryPointNotFoundException)
                {

                    n = UnsafeNativeMethods.sqlite3_close(db);


                }

#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }

    internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow)







|

|
>
>
|
>
>
>
>
>
>
>
|
|
<
>
|
>
>
>
>
>
>
|
|
>
|
>
>
|
>







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598

599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
#else
            lock (hdl)
#endif
            {
#if !SQLITE_STANDARD
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db);
#else
                ResetConnection(hdl, db, false);

                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }

    internal static void CloseConnectionV2(SQLiteConnectionHandle hdl, IntPtr db)
    {
        if ((hdl == null) || (db == IntPtr.Zero)) return;

        try
        {

            // do nothing.
        }
        finally /* NOTE: Thread.Abort() protection. */
        {
#if PLATFORM_COMPACTFRAMEWORK
            lock (hdl.syncRoot)
#else
            lock (hdl)
#endif
            {
#if !SQLITE_STANDARD
                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_interop(db);
#else
                ResetConnection(hdl, db, false);

                SQLiteErrorCode n = UnsafeNativeMethods.sqlite3_close_v2(db);
#endif
                if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError(hdl, db));
            }
        }
    }

    internal static bool ResetConnection(SQLiteConnectionHandle hdl, IntPtr db, bool canThrow)
Changes to System.Data.SQLite/SQLiteConnection.cs.
330
331
332
333
334
335
336







337
338
339
340
341
342
343
    /// </summary>
    private static object _syncRoot = new object();

    /// <summary>
    /// Static variable to store the connection event handlers to call.
    /// </summary>
    private static event SQLiteConnectionEventHandler _handlers;







    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region Private Data
    /// <summary>
    /// State of the current connection







>
>
>
>
>
>
>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    /// </summary>
    private static object _syncRoot = new object();

    /// <summary>
    /// Static variable to store the connection event handlers to call.
    /// </summary>
    private static event SQLiteConnectionEventHandler _handlers;

#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
    /// <summary>
    /// Used to hold the active library version number of SQLite.
    /// </summary>
    private static int _versionNumber;
#endif
    #endregion

    ///////////////////////////////////////////////////////////////////////////////////////////////

    #region Private Data
    /// <summary>
    /// State of the current connection
445
446
447
448
449
450
451
























452
453
454
455
456
457
458
    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
      UnsafeNativeMethods.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK
      SQLiteLog.Initialize();
























#endif

      _flags = SQLiteConnectionFlags.Default;
      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      //_commandList = new List<WeakReference>();








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    {
#if (SQLITE_STANDARD || USE_INTEROP_DLL || PLATFORM_COMPACTFRAMEWORK) && PRELOAD_NATIVE_LIBRARY
      UnsafeNativeMethods.Initialize();
#endif

#if !PLATFORM_COMPACTFRAMEWORK
      SQLiteLog.Initialize();

#if SQLITE_STANDARD
      //
      // NOTE: Check if the sqlite3_close_v2() native API should be available
      //       to use.  This must be done dynamically because the delegate set
      //       here is used by the SQLiteConnectionHandle class, which is a
      //       CriticalHandle derived class (i.e. protected by a constrainted
      //       execution region).  Therefore, if the underlying native entry
      //       point is unavailable, an exception will be raised even if it is
      //       never actually called (i.e. because the runtime eagerly prepares
      //       all the methods in the call graph of the constrainted execution
      //       region).
      //
      lock (_syncRoot)
      {
          if (_versionNumber == 0)
          {
              _versionNumber = SQLite3.SQLiteVersionNumber;

              if (_versionNumber >= 3007014)
                  SQLiteConnectionHandle.closeConnection = SQLiteBase.CloseConnectionV2;
          }
      }
#endif
#endif

      _flags = SQLiteConnectionFlags.Default;
      _connectionState = ConnectionState.Closed;
      _connectionString = "";
      //_commandList = new List<WeakReference>();

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
840
841
842
843
844
845
846







847
848
849
850
851
852
853
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_libversion();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else







    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_sourceid();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else







>
>
>
>
>
>
>







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_libversion();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern int sqlite3_libversion_number();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
    [DllImport(SQLITE_DLL)]
#endif
    internal static extern IntPtr sqlite3_sourceid();

#if !PLATFORM_COMPACTFRAMEWORK
    [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)]
#else
1463
1464
1465
1466
1467
1468
1469










1470
1471
1472
1473
1474
1475
1476
    ///////////////////////////////////////////////////////////////////////////

    #region SQLiteConnectionHandle Class
    // Handles the unmanaged database pointer, and provides finalization
    // support for it.
    internal class SQLiteConnectionHandle : CriticalHandle
    {










#if PLATFORM_COMPACTFRAMEWORK
        internal readonly object syncRoot = new object();
#endif

        ///////////////////////////////////////////////////////////////////////

        public static implicit operator IntPtr(SQLiteConnectionHandle db)







>
>
>
>
>
>
>
>
>
>







1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
    ///////////////////////////////////////////////////////////////////////////

    #region SQLiteConnectionHandle Class
    // Handles the unmanaged database pointer, and provides finalization
    // support for it.
    internal class SQLiteConnectionHandle : CriticalHandle
    {
#if SQLITE_STANDARD && !PLATFORM_COMPACTFRAMEWORK
        internal delegate void CloseConnectionCallback(
            SQLiteConnectionHandle hdl, IntPtr db);

        internal static CloseConnectionCallback closeConnection =
            SQLiteBase.CloseConnection;
#endif

        ///////////////////////////////////////////////////////////////////////

#if PLATFORM_COMPACTFRAMEWORK
        internal readonly object syncRoot = new object();
#endif

        ///////////////////////////////////////////////////////////////////////

        public static implicit operator IntPtr(SQLiteConnectionHandle db)
1513
1514
1515
1516
1517
1518
1519

1520



1521

1522
1523
1524
1525
1526
1527
1528
        {
            try
            {
#if !PLATFORM_COMPACTFRAMEWORK
                IntPtr localHandle = Interlocked.Exchange(
                    ref handle, IntPtr.Zero);


                if (localHandle != IntPtr.Zero)



                    SQLiteBase.CloseConnection(this, localHandle);


#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}", localHandle));
                }







>

>
>
>

>







1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
        {
            try
            {
#if !PLATFORM_COMPACTFRAMEWORK
                IntPtr localHandle = Interlocked.Exchange(
                    ref handle, IntPtr.Zero);

#if SQLITE_STANDARD
                if (localHandle != IntPtr.Zero)
                    closeConnection(this, localHandle);
#else
                if (localHandle != IntPtr.Zero)
                    SQLiteBase.CloseConnection(this, localHandle);
#endif

#if !NET_COMPACT_20 && TRACE_HANDLE
                try
                {
                    Trace.WriteLine(String.Format(
                        "CloseConnection: {0}", localHandle));
                }
Changes to readme.htm.
208
209
210
211
212
213
214

215
216
217
218
219
220
221
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>

    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>







>







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>
    <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>
Changes to www/news.wiki.
24
25
26
27
28
29
30

31
32
33
34
35
36
37
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>

    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>







>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    <li>The ErrorCode field of the LogEventArgs is now an object instead of an integer.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>The names and messages associated with the SQLiteErrorCode enumeration values have been normalized to match those in the SQLite core library.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Implement more robust locking semantics for the CriticalHandle derived classes when compiled for the .NET Compact Framework.</li>
    <li>Cache column indexes are they are looked up when using the SQLiteDataReader to improve performance.</li>
    <li>Prevent the SQLiteConnection.Close method from throwing non-fatal exceptions during its disposal.</li>
    <li>Rename the interop assembly functions sqlite3_cursor_rowid, sqlite3_context_collcompare, sqlite3_context_collseq, sqlite3_cursor_rowid, and sqlite3_table_cursor to include an &quot;_interop&quot; suffix.&nbsp;<b>** Potentially Incompatible Change **</b></li>
    <li>Prevent the LastInsertRowId, MemoryUsed, and MemoryHighwater connection properties from throwing NotSupportedException when running on the .NET Compact Framework. Fix for [dd45aba387].</li>
    <li>Improve automatic detection of the sqlite3_close_v2 function when compiled to use the standard SQLite library.</li>
    <li>Add protection against ThreadAbortException asynchronously interrupting native resource initialization and finalization.</li>
    <li>Add test automation for the Windows CE binaries.</li>
</ul>
<p>
    <b>1.0.82.0 - September 3, 2012</b>
</p>
<ul>