New Warnings, Illegal Casts, and other Delphi compiler changes in 10.2 Tokyo

The focus for the Delphi compiler R&D for the 10.2 Tokyo release was clearly the development of a new compiler for Linux. However, there were many bug fixes and several minor changes to the compilers for all platforms worth covering. Command Line Compilers are Large Address-Aware You can use the 4GB memory space for common line compilation, like it happens from the IDE since 10.1 Berlin. Notice that given the command line compiler has much less memory overhead (the IDE loads design time packages and libraries in its memory space), this gives the compilers even more room in memory. New Warnings There are new warnings in the compiler, mostly focused on helping find potential breakage when building applications for multiple platforms and different CPU types: IMPLICIT_INTEGER_CAST_LOSS W1071 Implicit integer cast with potential data loss from '' to '' IMPLICIT_CONVERSION_LOSS W1072 Implicit conversion may lose significant digits from '' to ''" COMBINING_SIGNED_UNSIGNED64 W1073 Combining signed type and unsigned 64-bit type - treated as an unsigned type" Only the last of these 3 is on by default. You can disable it with a directive like {$WARN COMBINING_SIGNED_UNSIGNED64 OFF}. You can also turn each of the warnings in an error. For more information about this issue and a complete list of the warnings (and their ID, used for configuration) is available at http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Warning_messages_(Delphi) Dynamic Arrays and Pointers Assigning a dynamic array to a pointer is now considered an error, given this breaks reference counting on ARC platforms -- but can cause problems also on others. You can still do it (if you know what you are doing!) by using a hard cast. Changes to Namespace Resolutions Rules References do dotted unit names from uses statements have become a little more flexible. In the past, it had to be a direct match or reply on unit aliases declared in the project. Now the rule is a little more flexible. The compiler searches the non-prefixed name first, then iterate optionally specified namespaces. So, for example, "uses Classes" will first look for a unit called "Classes.pas", than go for "System.Classes.pas" and finally search in the FMX and VCL namespaces. These new rules should be largely compatible with the old ones, as they should resolve more scenarios automatically, but specific projects with duplicated names and an odd use of aliases might end up behaving differently. Allow Undefined to LLVM Linker By default, the compiler asks the LLVM-based linker to resolved all external symbols (for DLLs and shared object files) passing the "--no-undefined" option to it. However you can use the "--allow-undefined" option to disable the standard behavior (and avoid indicating that linker option). This allows you linking when the symbols are not available at compile time. Occasionally this feature is handy on the Linux platform.
Read More

RAD Studio 10.2 Tokyo support is available

We have just released a new EurekaLog build 7.5.1.151 with RAD Studio 10.2 Tokyo support. Changelog (since 7.5.1.0): Important: Debug information format was completely changed. Be sure to test your applications Important: Added a major upgrade to bug tracker code. Be sure to test your applications Important: BugID generation alg was changed. Be sure to test your applications Important: EurekaLog will now store configuration in .eof file instead of .dof, .bdsproj, .dproj, etc. Added: Support for 10.2 Tokyo Added: ecc32 will now modify uses list in your .dpr file to match specified configuration Added: --el_prepare switch is added to be used when --el_alter_exe is used Added: New option to stip all string names from debug information and store it in external file Added: Debug information's and ZIP's passwords are now saved locally on developer machine - to be used by application and Viewer (this simplifies local debugging when passwords are set). OnPasswordChange event will not be called Added: New "--el_password=debug-info-password" command-line option can be passed to application to decrypt encrypted debug information. OnPasswordChange event will not be called Added: Our own implementation of XML, XML-RPC, and SOAP. We no longer use RTL's implementation, therefore now we have support for bug tracker's API even on old IDEs Added: New options for bug trackers (new fields, append call stack instead of full bug report, links, text limits) Added: A helper "Connect" button in EurekaLog project options dialog to retrieve project names, users, field names, components, areas, and other info for bug tracker Added: Working hyper-links support in bug tracker success message via TaskDialogs (Vista+) Added: BugID tab in EurekaLog project options dialog - allowing you to customize uniqueness without writing OnCustomBugID event handler Added: New column in call stack: "Source" (e.g. actual .pas file name) Added: Threads selection to hang detection page Added: Support for MessageBox from NT services Added: "Lookup Error" option in Viewer - there is a new toolbar, as well as new context menu item for "General" tab Added: ELogging unit implements log capabilities. EurekaLog will stream log into CodeSite-compatible format. Currently it has no UI control. Use ELogReopen function to stream log to the specified file Added: (Delphi only) EurekaLog units in uses list are wrapped into IFDEF block Added: Call stack, modules and processes use different colors now. For call stacks: red indicates exception line, black - stack frame entry (positive), grey - RAW (could be false-positive), other colors - service entries Added: Support for DataSnap applications. Do not forget to enable EurekaLog for background threads (either as "Enable for RTL threads" or as SetEurekaLogStateInThread in OnConnect handler) Added: Handler name property for exception info and ability to filter with it. Handler name indicates handler which is processing the exception, it can be used to distinguish between VCL, Thread, DataSnap exceptions, etc. Added: Ability to filter by descendant classes Added: ACompareForCount argument to DumpAllocationsToFile routine Fixed: Reduced ecc32/emake memory footprint, thus allowing to post-process larger projects Fixed: Debug information design-time performace optimizations (reduced compilation time) Fixed: Debug information run-time performace optimizations (reduced startup time) Fixed: Minor optimizations for call stack to string render Fixed: Display bug in detailed EurekaLog dialog tabs when not all tabs were showing Fixed: [10.1 Berlin] Weak references are no longer detected as leaks Fixed: A "recursive area removed" mark may be left in call stack even if area's items were filtered out Fixed: Fatal errors (e.g. panic mode) now properly set terminate option in dialogs Fixed: Possible crash on startup when using certain 3rd party memory managers Fixed: Possible crash when EurekaLog's debug mode is enabled Fixed: XML header of bug reports Fixed: Added workaround for OTA bug when {$E ext} is used in project Fixed: (C++ Builder only) Possible crash when handling certain exceptions Fixed: Firebird Embedded in Viewer was upgraded to 2.5.6. This solves a rare encoding problem when using Firebird backend Fixed: (Delphi 2005 and earlier) Bug in workaround for http://qc.embarcadero.com/wc/qcmain.aspx?d=3018 Fixed: Checkboxes not respecting default state when switching between dialogs (e.g. MS Classic -> EurekaLog Detailed) Fixed: Visual glitches in EurekaLog dialogs when VCL styles are used Fixed: Compatibility with 3rd party software of password-encrypted ZIPs Improved: New call stack/assembler encryption when encrypt password is set for debug info Improved: Better call stack filtering from EL service routines when encryption is enabled Improved: Any share violation error during compilation will report which process is holding the file Changed: ecc32.exe and emake.exe are the same file for all IDEs. Current IDE is selected based on ecc32/emake file location or via --el_ide=num command-line option Removed: Web-based bug tracker support
Read More

TZipFile with Password Encryption (Part 2)

The first part of this article describes a simple but limited way to read password encrypted zip files with a derived TZipFile class. The limitations are it can only read but not create encrypted zip files the size of the zip files is limited by the available memory While this solution does the job in the scenario it was built for, I cannot say that I was really satisfied with that. So I investigated ways how these limitations can be overcome. It turned out that it was not that easy as I anticipated. As we found out in the first part TZipFile exposes some hooks for us to intercept the reading and inject our encryption routine. For unknown reasons (at least to me) the corresponding hooks for writing the zip file are missing. My first idea was to replace the compression handler with a routine similar to the decompression handler to add these hooks, but the underlying field holding these handlers (FCompressionHandler) is private. At least I could register an alternative pair of compression/decompression handler for the deflate method, even if I had to copy most of the original registration code. Luckily this allowed me to put my decompression hook directly into the code without using the CreateDecompressStreamCallBack – something that had already disturbed my feelings about the first implementation. The new class constructor turns out to be a bit longer than the previous one where a large part is mostly just copied from the original class constructor.class constructor TEncryptedZipFile.Create; begin RegisterCompressionHandler(zcDeflate, function(InStream: TStream; const ZipFile: TZipFile; const Item: TZipHeader): TStream var PItem: ^TZipHeader; LStream : TStream; LIsEncrypted: Boolean; begin LIsEncrypted := HasPassword(ZipFile); if LIsEncrypted then begin PItem := @Item; LStream := TEncryptStream.Create(InStream, TEncryptedZipFile(ZipFile).Password, Item); PItem.Flag := PItem.Flag or 1; end else LStream := InStream; Result := TZCompressionStream.Create(LStream, zcDefault, -15); end, function(InStream: TStream; const ZipFile: TZipFile; const Item: TZipHeader): TStream var LStream : TStream; LIsEncrypted: Boolean; begin // From https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT // Section 4.4.4 general purpose bit flag: (2 bytes) // Bit 0: If set, indicates that the file is encrypted. LIsEncrypted := (Item.Flag and 1) = 1; if Assigned(TZipFile.OnCreateDecompressStream) then LStream := TZipFile.OnCreateDecompressStream(InStream, ZipFile, Item, LIsEncrypted) else if Assigned(TZipFile.CreateDecompressStreamCallBack) then LStream := TZipFile.CreateDecompressStreamCallBack(InStream, ZipFile, Item, LIsEncrypted) else if LIsEncrypted and (ZipFile is TEncryptedZipFile) then LStream := TDecryptStream.Create(InStream, TEncryptedZipFile(ZipFile).Password, Item) else LStream := InStream; Result := TZDecompressionStream.Create(LStream, -15, LStream <> InStream); end); end;As some of you may have noticed there is a little hack needed to get the encryption working: the Item parameter is declared as constant, but we need to manipulate the Flag field to indicate encryption. To outsmart persuade the compiler to let us change the Flag field we make use of the fact that a const parameter of a record type is nothing else than a pointer. After all this was not that difficult as it looked in the first place, so we can now move on to the implementation of the encryption stream. Referring to the original link of the PKWARE APPNOTE.TXT was a bit disappointing. The encryption algorithm was not explained in the same detail as the decryption steps. Seems I had to step back and try to understand the decryption sequence in more detail to deduce the encryption steps from it. Having a TDecryptStream and TEncryptStream class sort of demanded a common ancestor class. In addition I extracted the plain decryption and encryption steps into a separate TCryptor class (one class  – one purpose). This is the public interface:type TCryptor = class ... public procedure InitKeys(const APassword: string); procedure DecryptByte(var Value: Byte); procedure EncryptByte(var Value: Byte); end;The base crypto stream class looks like this:type TCryptStream = class(TStream) private FCryptor: TCryptor; FPassword: string; FStream: TStream; FStreamStartPos: Int64; FStreamSize: Int64; FZipHeader: TZipHeader; protected procedure InitHeader; virtual; abstract; procedure InitKeys; procedure ResetStream; property Stream: TStream read FStream; property ZipHeader: TZipHeader read FZipHeader; public constructor Create(AStream: TStream; const APassword: string; const AZipHeader: TZipHeader); destructor Destroy; override; function Read(var Buffer; Count: Integer): Integer; override; function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override; function Write(const Buffer; Count: Integer): Integer; override; end;Both methods Read and Write just raise in EZipInvalidOperation exception. The TEncryptStream and TDecryptStream each override one of these methods leaving the other one raising that exception.TDecryptStream = class(TCryptStream) protected procedure InitHeader; override; function Skip(Value: Int64): Int64; public function Read(var Buffer; Count: Integer): Integer; override; function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override; end; TEncryptStream = class(TCryptStream) protected procedure InitHeader; override; public function Write(const Buffer; Count: Integer): Integer; override; end;One of the problems I encountered was the fact that the original TZipFile implementation uses Seek during decrytion to rewind the stream to a previous position. This didn’t any harm in the previous part as we used a memory stream there, but here we don’t have this luxury. Just moving the stream position will not work in this case because the decryption algorithm uses a state which is updated with each byte decrypted. The current implementation uses a brute force approach and re-reads the whole stream from the beginning when a Seek wants to move backwards. This may be optimized for better performance in a future implementation. I would like to note that things could be implemented much easier when done inside the original TZipFile class. Particularly the Seek operation would be one of the first I would try to eliminate. I might as well redesign the class var hooks approach into a more old fashioned virtual method or standard event approach (just more stress free in multi-thread scenarios). Perhaps someday we will see encryption being part of the stock implementation. As before, the complete source can be downloaded from here:  EncryptedZipFile BTW, please notify me about any bugs and issues you may find.
Read More

Upcoming event: TMS Day in Fredericia, Denmark on May 18th

We are excited to announce that Jens Fudge, Embarcadero MVP for Denmark, and TMS software are planning a TMS day in Denmark on May 18th.

All day, sessions will be spent on TMS VCL components, TMS FNC components and TMS Cloud components and with also sufficient session time allocated to handle your specific questions on TMS components. The sessions will be given by Bruno Fierens, Embarcadero MVP in Belgium and CTO from tmssoftware.com.

All sessions will be in English.

In tentative program

9h00
TMS FNC Controls architecture
Insight in the architecture of the TMS FNC controls and a brief introduction to using the TMS FNC library to write custom controls for VCL, FMX, LCL.

10h00
TMS FNC Controls overview
Overview of TMS FNC UI Controls in the TMS FNC UI Pack, TMS FNC Chart, TMS FNC Blox

11h00
TMS MQTT
Use the TMS messaging component for machine 2 machine messaging from Windows, iOS, Android, Android, Linux.

12h00
Lunch

13h00
TMS VCL Components tips & tricks
An overview of less known features in TMS VCL components

14h00
TMS Google Mapping components
Overview of features and advanced capabilities in the TMS Google Mapping components for VCL & FMX.

15h00
TMS Cloud Components & myCloudData
Access popular cloud services from VCL and FMX applications. Use service agnostic cloud file storage access. Use cloud data storage with the myCloudData service.

16h00
TMS PDF Library
Use the cross-platform PDF generation engine and applying the PDF lib for automatic PDF generation from several TMS components.

Location

Archersoft ApS
Vesterballevej 5
7000 Fredericia
Denmark

Register now!

Sign-up now for the TMS Day in Denmark in Fredericia, Denmark on May 18th, 2017.
The cost of the TMS Day is only a small fee of 35 EUR (VAT exclusive) for the food and drinks during this day.

Don’t delay your registration as the number of seats is limited.

Read More

Read More

Google, Mobile, and You. Are You Good?

I put my Delphi development on hold a few months ago so I could work on creating a responsive website for my software. The hardest part for me was trying to find a layout I was happy with. I took a little inspiration from the Embarcadero Communty website. I settled on a Bootstrap 9 X 3 layout. And now it's done and I can move on.It's only been a couple days but I have already seen a 300% increase in traffic to my website.Dave Collins from Software Promotions has put together a 5 minute video that talks about Google's big shift toward mobile first indexing. I strongly encourage you to watch this video. Mobile-friendly isn’t necessarily mobile-friendlyI'm just an Independent Software Deveopler like many of you. I felt compelled to share what I have learned over the past three months. We all love Delphi and the opportunities it gives us to create software and apps. You can have the best software or app out there but if people can't find it, it's not a good thing. Don't let this happen.I look forward to getting back at it. It feels good to know thay my development efforts will have a fighting chance.Semper Fi,Gunny Mikezilchworks.com
Read More

New Release Model in Action!

This week, we are pleased to release RAD Studio 10.2 Tokyo. It celebrates our many customers in Japan and is a testament to the true global nature of our company. If you remember, one of our Boot Camps had representatives from over 200 countries!   RAD 10.2 is an important release in many ways. It is a truly BIG one. The Enterprise and Architect versions contain a Linux compiler that has been anticipated for years. It also has many other enhancements and fixes. It is even more important as a demonstration of our new release model and commitment to continued and rapid improvement of the core product. It nicely highlights the benefits of update subscription (aka maintenance). A preview of the product was available early for these customers.   We had four release in the last 12 months (minor and major)! We are continuing to improve the upgrade process, but regardless, this is an excellent value. And while  the required uninstall is cumbersome, pretty much everyone agrees that the process has become much smoother after the release of 10.1 Berlin. The GetIt installer is far quicker too.   The improvements in Quality and Stability have been well received and we will continue to do even more.  I think that the biggest challenge is making this process work more seamlessly with component partners, but even there we see some improvement. Our technology partners, similar to our maintenance customers, have had 10.2 for almost two months, which results in better stability and quality. The feedback on quality is great, but partners are also excited to build new capabilities that leverage the Linux backend. This will continue to move our ecosystem forward.   The new release model challenges us to continue to deliver value to customers all the time. Our PM team is very proud of the extent of our Windows 10 support, which is the best in the industry (even ahead of Visual Studio in certain areas). FMX is a true gem for anyone that wants to build native mobile apps fast. There is so much more to come on that front. Of course the core IDE and compilers will continue to get better too. We gave a taste to some IDE changes with RAD 10.2, which, while subtle are an example of the productivity focus that we want to embrace.   One area that I am particularly excited about is to give you template applications that get you started with new projects faster. We initiated this with some free games for Berlin. Literally thousands of dollars worth of source code was provided for free through GetIt to update subscription customers. With 10.2 we plan to give even more source code. For example, next week we will deliver a Healthcare app that uses RAD Server and Beacons. We have several more in the works that will expedite multi-tier projects with RAD Server. Many are asking for these to be available in a hosted environment, which is being considered. The best thing is that these will come through GetIt, so installation will be simple. Some of the Konopka controls updates will be delivered that way too, again making the ongoing relationship even more valuable.   We want our customers to feel special. By buying RAD Studio you are part of an elite community of developers where we challenge each other to constantly innovate and make amazing applications. There are many good developer tools out there, but if you want fast, yet robust development, RAD Studio is the best answer.
Read More

Tokyo, InterBase 2017, Linux and Codegen = Secret Weapons

“The release of RAD Studio 10.2 not only takes a big step forward with Linux support, but it also leaps forward with a more scalable RAD Server, deeper Windows support and the quality developers expect. We are also continuing to provide industry leading support for Windows 10 and the Windows 10 Store through our VCL framework.”
 
-Nick Hodges, head of product management at Embarcadero.
 
Excerpt from our recent RAD Studio 10.2 Press Release
 
 
   
 
 
RAD Studio 10.2 – Now Available
 
RAD Studio 10.2 includes the first RAD Studio Linux compiler, improved IDE menus for faster navigation, a host of FireMonkey updates and new features, new TDataSet capabilities, multi-tenancy support in RAD Server, updates to FireDAC, a number of RTL enhancements, greatly improved…
 
Read More!
 
Download RAD Studio 10.2 Now
 
The fastest way to develop cross-platform Native Apps with flexible Cloud services and broad IoT connectivity.
 
BUY RAD Studio 10.2
 
Start a FREE Trial of RAD Studio 10.2 Today
 
Download Free Trial RAD Studio 10.2
 
 
 
 
 
 
Fast Development Rules – Use Delphi and FMX as secret weapons. By Atanas Popov
 
Read the follow-up to Atanas Popov article on the importance of fast development as he talks with Eli M. of Peacekeeper Enterprise about how they use Delphi and FMX as their secret weapon.
 
Read More!
 
Jim McKeeth, Embarcadero Chief Evangelist, meet Embarcadero Japanese MVP.
 
Meet HOSOKAWA Jun, our MVP from Japan. He is involved in mobile, game, artificial intelligence, virtual reality, and mixed reality development. Read the full interview with him and Jim McKeeth.
 
Read More!
 
 
 
 
 
 
 
 
Launch Webinar for RAD Studio 10.2 Tokyo
 
Join Embarcadero Product Management Team to learn about the new release of RAD Studio 10.2, including the first LLVM based Linux compiler for Enterprise development, updates to FireDAC, FireMonkey, the RTL, C++Builder compilers, multi-tenancy support for RAD Server and more…  
 
RAD Studio™ is the fastest way to write, compile, package and develop …  
 
Register Now!
 
 
Overview of the RAD Studio 10.2 release
 
The first RAD Studio LLVM based Linux compiler for Enterprise development
   
Improved IDE menus for faster navigation
   
A host of FireMonkey updates and new features
   
Multi-tenancy support in RAD Server
And much more.
 
Read More!
 
 
 
 
 
 
What’s New in C++Builder 10.2: Part 2 – Code Generation
 

RAD Studio 10.2 Tokyo is released, and we would like to let you know some of what you can expect to see new on the C++Builder side.  While the majority of work is for Linux, which will be available for C++ in 10.2.1, we’ve worked on three key areas:

Improved linking
Improved code generation
Improved debugging
 
Read More!
 
InterBase 2017 – Now Available – Embed, Deploy Relax
 
InterBase 2017 delivers the fastest version of InterBase yet with new language features, server wide performance monitoring and enhanced transaction handling.
 
Read More!
 
The trial and developer editions of InterBase 2017 are available for free
 
Download the Trial Version
 
 
 
 
 
 
Save over 54% and Get the Best Tools in 2017
 
 •  Architect at a 15% discount + FREE RAD Server site license + 15 months initial maintenance subscription
 •  Enterprise at a 10% discount + FREE RAD Server 10-device license + 14 months initial maintenance
 •  RAD Studio Architect Suite : Save over 54% with this InterBase Server, RAD Server and RAD Studio bundle
 •  RAD Studio – Enterprise Suite: Save over 47% with this InterBase Server, RAD Server and RAD Studio bundle
 •  Free RAD Bonus Pack for all on Update Subscription
 
 
Get 10.2 Tokyo Today!
 
Offers end 31 March 2017!
 
 
 
    More Developer Resources
 
 
 
Configure Delphi and Red Hat or Ubuntu for Linux Development
   
The Sarina DuPont Self Driving Car Episode
   
Delphi Blogs of the Week/Month #51
   
 
RAD STUDIO 10.2 – Available Today With Linux for Delphi
   
What’s New in C++Builder 10.2: Part 3 – Debugging
   
Delphi 10.2 has been Released Today

Read More

Read More

Boost your productivity with TMS components & RAD Studio 10.2 Tokyo

Yesterday Embarcadero released Delphi, C++Builder and RAD Studio 10.2 Tokyo:
https://www.embarcadero.com/products/rad-studio/whats-new-in-10-2-tokyo

For our registered users, already several products are ready for this new RAD Studio version!
So get started today with your Windows or cross-platform development in 10.2 Tokyo with TMS VCL, FMX and FNC components.

TMS rollout of components with RAD Studio 10.2 Tokyo support:

  VCL Windows application development
  FMX cross-platform application development
  FNC cross-platform & cross-framework application development
  Developer tools for Delphi developers

Our team is working hard to continue to add RAD Studio 10.2 Tokyo support to our other wide range of component products. You can track here the progress of our work to cover other products. For trial users, RAD Studio 10.2 Tokyo support will follow soon.

Read More

Read More

Kylix: The Real Lowdown – I wrote this in 2000 too

A while ago – while researching yesterdays post – I came across the below article that I wrote back in august 2000 for The Delphi (by Pinnacle Publishing – long gone by now) and on-line at http://www.delphidevelopernewsletter.com/dd/DDMag.nsf/WebIndexByIssue/B8FC16D8103A3760852568F600559A83 I found a cached copy first at http://www.txsz.net/xs/delphi/2/%E6%8A%80%E5%B7%A7%E5%8F%8A%E7%BB%8F%E9%AA%8C/KYLIX%EF%BC%9A%20%E7%9C%9F%E7%9B%B8.HTM and back-tracked from there. Since the wayback machine isn’t indexed, I salvaged the […] … Read More

Read More

My Top 10 Aurelius Features – #1 Maturity

Finally, My Top 10 Aurelius Features series has come to an end. And the number 1 of the list is Maturity. Aurelius has been first released in early 2012. Since then, in five years, it has received 33 releases! With the user feedback received during all the time, I’m confident that Aurelius feature set is pretty extensive. For example, you can build applications for all supported Delphi platforms: Windows, Mac OS X, iOS, Android and Linux. The number of supported database systems is impressive: Oracle, MySQL, SQL Server, PostgreSQL, DB2, Firebird, SQLite, NexusDB, ElevateDB and the list goes on. The same can be said about the component libraries you can use to access the database: the list of 15 options include FireDac, dbExpress, ADO, UniDac, among others. Maturity also means that you can trust it, because it just works. Aurelius test suite includes hundreds of unique tests, which makes up thousands of tests because we make sure that they work in all the supported platforms and servers. This means that you can be sure it will work on Windows, using dbExpress to access an Oracle database, the same way it will work on Linux, using FireDac to access a MySQL database. In the end, why I really like this maturity feature? Because it makes my life easier and happier. Lower support because there are no known bugs that stand for too long. And happier customers because they have the features they need. We’d love to hear your comments about it. Do you agree with this list? What would be yours? Post your opinions and comments below, visit our website, download TMS Aurelius trial and let us know what you think. Don't forget to subscribe to our YouTube channel to get notified about upcoming videos!
Read More