Licensing: Using 3rd Party/OSS software or images in your commercial product.

DISCLAIMER: I am not a lawyer, solicitor or trained in any legal profession. If you act on anything in this article, it is at your own risk. You should consult your own legal counsel before exposing your company to risks & liabilities.


Now to the article…

Most Software Developers just want to use free, software libraries, code or graphics to quickly get over a hurdle and sprint away from the problem. We typically just want to embed a small piece of it in products we’ve been asked to make. What we don’t want is complex licensing terms, restrictions, impositions and uncertainty. We’d rather find a less optimal component with lesser licencing issues if it meant we could get beyond our current impasse.

There is no single thing as an Open Source Licence. To me, Open Source is a paradigm where one develops software or other content such as images or documents with community help, feedback, and some kind of public use ideology. That is completely distinct from the way in which that content can be consumed, adapted and redistributed by companies or individuals; which is where we enter the licencing minefield. There is no one “Open Source Licence”, but many licences that Open Source Software is available under. Each has quirks, legacy, purpose and definitions.

To help that, I’ve compiled a list of software licences encountered in my travels, and provided my personal interpretation of those. Use at your own risk.



Here is a selection of popular licences I believe to be entirely compatible with “embedding software/images under those licences into a larger commercial product”. Typically that means you aren’t just bare-face selling what’s already been made by the OSS community, but creating an app that needs (for example) a bit of code for authentication, or some graphics for your buttons.

I typically look for a licence that:

  • Is relatively simple to understand
  • Allows you to make modifications to the source code/image with little impact on your processes
  • Allows royalty free redistribution of the code/image (particularly when embedded in a larger application)
  • Does not impose licence terms on the work you have created
  • At most, requires you to attribute or reproduce licences ‘somewhere’.
  • Does not require you to expose modifications of source code available back to the community.

Complexity is a subjective viewpoint of how much text to read and/or how complex the terms and conditions and caveats are.





BSD 2 Clause

Reproduce entire copyright ,licence and disclaimer in documentation or other materials.


BSD 3 Clause

As the 2 clause, but you are not allowed to use the technology or names to endorse or promote your product without permission.



The copyright notice and the permission notice need to be included
in all copies or substantial portions of the Software. ‘The software’ doesn’t mean ‘your software’, but the
original work.I would, however, attribute to be polite.


Apache 2.0

Include/attribute the original licence in the installation media/documentation, typically this is as simple as reproducing the NOTICE file for that component in your documentation.


Has a lot of text to go through compared to BSD 3 clause.

Microsoft Public Licence (MS-PL)

You’re not allowed to use trademarks/name of the

You (pretty much) have to include the licence as attribution.

Distribution requires your licence to comply with MS-PL’s
licence, but doesn’t mean your licence has to be MS-PL, it just has to not
infringe on the original terms.


Creative Commons PD (CC0)

Do not imply endorsement of the originator.

No attribution required.


Creative Commons CC BY 3.0

Attribute the originator & link to the licence.

Do not use the originator as an endorsement.

Clearly state if modifications of the original works have
been made.

“Work” means the original work, not your work – your work
is the “Adaptation”.

High – purely on word count and inappropriate / unclear
consideration for use in software products.


Licences which didn’t make the list

Mozilla Public Licence 2.0

This licence is just too wordy and in it’s own words “copy-left”. Be warned. It requires you to do more than you’d like to distribute a program that includes code from MPL. Yes, in the simplest case where the original is unmodified, all you have to do is make sure that the source code is available from the link you provide, or on request and made available in a reasonable time frame/by reasonable means. But to me, the extra conditions place on it, and the slightly scary ‘copy-left’ statement makes me walk away.



LGPL 3.0

You may wonder why the Lesser Gnu Public Licence hasn’t even made my list. Apart from doing its best to not use relevant technical terminology, it adds conditions to distribution (aka “convey”) of your end product “a combined work” that uses the library you’ve downloaded from the web.

The most alarming condition is 4d – that you have to allow end users to drop in replacement libraries and/or allow end users to relink your product to them – that could present s significant security and support issue. Clause 4b and 4c also elevate the licence to GPL instead of LGPL which is viral.

There is another GPL licence – the Gnu Public Licence. That’s definitely not compatible with a commercial software product unless all you’re selling is support & training and you don’t mind your competitors building and selling your software too without any kickback.



SIL OpenFont Licence

This was nearly in my list, but you have to be careful with naming any icons you’ve modified (derivative works) as there are conditions on the use of names.

The basic SIL font licence FAQ page indicates at the bottom that it is Share-A-Like, which makes my hair stand on end – and typically means (to me) you’d have to include the original font as a separate file for your end users to be able to use.



CC  BY SA 3.0

Share-a-like –  “ If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.” – scared me off. I don’t want my product or even a tiny part of it to suddenly become ‘Open’ because I’ve tweaked your broken icon.


Icon packs and existing trademark images

Typically your app will want to present a login button for using social media accounts, or buttons to share and tweet. But when it comes to using trademark or copyright images to represent these, alarm bells need to ring in your head.

Even if the icon pack licence file claims the icons are free to use or modify, you are not usually free to do so on such images. You need to check with the owner of the trademark image, and investigate what restrictions of use they impose on it. Typically this means not altering the colours or image.

Facebook’s DOs & DON’Ts

Twitter’s brand asset guidelines.

(Thanks to @IPWright for reminding me to add this section)



My SVG Notes

SVG (Scalable Vector Graphics) is pretty awesome, especially so for 2d flat-look icons in your applications, or as clipart in your presentations.

I’ve recently been doing just that, using SVG for flat icons in a mobile app; and compiled some personal notes and links you might find useful.



We are now at the point where you’d be hard pressed to find an Internet Browser that can’t do the SVG dance. shows us what’s compatible or not.

Basic Usage

Craig Butler wrote a nice short overview of the different ways you can embed Scalable Vector Graphics into your web page. I’ve provided some more links later in my blog which expand on those methods.


My notes on SVG-CSS backgrounds

If you find that you have to use SVG in a background you may be faced with a bit of a shocker – you can’t easily change the colour or rotation of the SVG element!

Luckily you can specify the background size (CanIUse, W3C).

background-image: url('xxxx.svg');
background-size: 24px 24px;
background-position: center;

However, the colour is taken directly from the SVG file. So if you need a different colour you either use an SVG editor (see later) or edit the SVG as a text file and fill in properties like stroke=”red” fill=”red” as attributes in the required element. See this tutorial for more details.

Rotation can also be a pain when using background SVG images. If the SVG image isn’t already rotated how you want it, you’d have to either

  • edit the SVG with an editor to rotate it and re-save,
  • rotate the HTML element that is used for the background SVG,
  • in the SVG file, add an attribute to the drawing element you require: transform=”rotate(-45 100 100)“, where the parameters are (degrees, x rotation point, y rotation point). See this example.




I’ve tried google’s on-line svg-edit, and for quick jobs it’s really handy, but a little buggy (had to press cancel while loading to get the SVG to load!)

I’ve not tried the following editors, but they looked very promising.



Unless the editor already supports it, you may want to optimize your SVG afterwards.


More Tips and Tricks with SVG SVG tutorials

W3CSchools SVG reference


SVG Icon/Image Resources

Here are a selection of Icon packs with commercially permissive licences. Don’t forget to read licences carefully before using, and attribute the original sources in the manner they state.


Open Clipart


Custom MIT style licence, prevents re-hosting or selling the ‘set’ of icons.


Zurb Foundation Icons

Has no explicit licence, but indicates free.


Icon Monster

This has a custom licence which is very permissive, but you can only use 50 icons.



They also do commercial packs



A MIT style licence


Open Iconic

MIT licence (svg and PNG)

Be careful, earlier versions of the Iconic packs were Creative Commons Share-a-Like which I believe the licences are ambiguous enough to not be suitable for commercial apps. There’s also a commercial version of this library. I found some scaling issues with these icons, and some required editing before they could be used.


A list of other Icon Packs


Elusive-Icons Web Font

This is under the SIL OpenFont licence. I haven’t checked this licence thoroughly, but the intent is set right. However, I need to spend more time reading the specific EULA to ensure this is compatible with commercial software.



SQL Server – TempDB How many files?

As explained by Paul Randal. Scripts by Paul Randal.

Step 1: Make sure this information isn’t out of date!

Step 2: Detect if your server has a problem with tempDB contention by running a script.

Step 3: If you have contention, then…. If you have less than equal to 8 cores, ensure you have as many tempdb files as you have cores. If you have more than 8 cores, follow a growth formulae, and test the impact of the change (see Paul’s blog above). Note: You do not need more log files.

Step 4:  Make sure all tempdb files are the same size.

Step 5: Make sure your tempdb files are sized to your typical operational workload, as they will shrink when the server resets.


SQL Server – Detection of Implicit Conversions

These notes were taken whilst watching the fabulous PluralSight course “Why Physical Database Design Matters, Datatypes and Query Performance – Kimberly Tripp.”


TL;DR: Writing SQL statements which compare or join columns of different data types can cause performance problems. To locate when this happens, you can use two scripts. One to locate implicit conversions in comparisons/ordering and one to locate probe residual conversions typically found in ‘joins’.

Extra content in this blog post has come from Jonathan Kehayias’ blog Implicit Conversions that Cause Index Scans, and  Rob Farley’s blog.


Implicit Conversions

When executing an SQL statement which tries to compare char, nvarchar, varchar, and some datetime types with each other SQL server may be prevented from using any indices and need to convert the data in the rows to perform the operation.  This chart shows the danger zones – in Yellow. This is when an index scan is performed due to conversion rather than a more robust outcome (no conversion/index seek/obvious failure). The results may differ depending on your collation settings too. – But in general do not allow users to write ad-hoc statements and make sure that statements use the correct datatype!

The blog Finding Implicit Column Conversions in the Plan Cache details a script to help locate if any conversion has taken place recently in your plan cache. In testing I’ve also seen conversion from int to bigint be reported by this script.


Residual conversions

“Probe Residual” is the name for conversions which happen implicitly during join execution (a residual converted column value is used). This is usually only a problem when foreign key relationships aren’t part of the integrity (e.g. soft keys), and the converted column has a large number of rows.

Sometimes these appear in the SQL Server Execution plan as scalar computations immediately before the join. If you hover over the join block and look for “Probe Residual”, you’ll know it has happened. However, there’s no need to dig into each query. You can just download and execute this script to find any probe residual conversions – thanks Kimberly! Just try joining an int field with a bigint field, and you’ll get a hit from this script.


SQL Myth: The NULL bitmap is only added to a record when it’s got nullable columns

As seen in my previous post SQL How To: Dump the contents of a SQL Page, I mention right at the end that we have a null bitmap, yet our table did not contain any nullable columns.

We can prove this further by creating a variant of our original table with a nullable column, and another with the same column non-nullable to see the difference.

CREATE TABLE PersonWithNullable(
FirstName char(40),
LastName char(40),
NickName char(40) NULL,
Age int )

INSERT INTO PersonWithNullable VALUES ('Giles','Middleton', NULL, 40 )

EXEC sp_AllocationMetadata 'PersonWithNullable'

Results in:


And when we inspect the page null bitmap, it yeilds (our database is called ‘test’)


DBCC PAGE('test', 1,179,3)

Results in


0400  04 is actually

0004 (4 columns in little endian order) plus the null bitmap 04 (00000100)

This ‘3rd bit’ represents column 3. Indicating it is null.


Watching the bits go by

To demonstrate this nullable bit pattern, let us create  table of all nulls and fill it with different patterns

CREATE TABLE PersonWithAllNullable(
FirstName char(40) NULL,
LastName char(40) NULL,
NickName char(40) NULL,
Age int NULL )

INSERT INTO PersonWithAllNullable VALUES (NULL,'Middleton', 'Gilesey' ,40 )

INSERT INTO PersonWithAllNullable VALUES ('Bob',NULL, 'Bobby' ,41 )

INSERT INTO PersonWithAllNullable VALUES ('Matt','Didd', NULL ,42 )

INSERT INTO PersonWithAllNullable VALUES ('Simon','Hedgeson', 'Hedgey', NULL )

After using our stored procedure and DBCC PAGE we saw…

1FirstNameNull 2LastNameNull 3NickNameNull


Let’s finish off our test

To make sure I wasn’t imagining things, lets get rid of the nullable columns and see if the bit mask byte is still there.

CREATE TABLE PersonWithNoNullable(
FirstName char(40),
LastName char(40),
NickName char(40),
Age int )

INSERT INTO PersonWithNoNullable VALUES (‘Giles’,’Middleton’, ‘Gilesey’ ,40 )

After using our stored procedure and DBCC PAGE we saw…



Yep, an extra byte we don’t need!


The final twist

A table with 9 Nullable columns will cause an extra byte to be added to the row size just for the null bitmap we will not use.

c1 tinyint,
c2 tinyint,
c3 tinyint,
c4 tinyint,
c5 tinyint,
c6 tinyint,
c7 tinyint,
c8 tinyint,
c9 tinyint)

INSERT INTO NineCols VALUES (0xff,0xfe,0xaa,0xbb,0xcc,0xdd,0x22,0x33,0xee)

EXEC sp_AllocationMetadata ‘NineCols’

Resulted in…



That’s an extra byte. For our particular record, that’s quite an overhead.

So the lesson there kids, is if you are about to exceed 8, 16, 24, 32 (etc) columns, you’ll add another byte per row to your record for null bitmap storage, even if you do not use nulls.

SQL How To: Dump the contents of a SQL Page

This technique uses an excellent stored procedure developed by Paul S. Randal, which I’ve copied here for safe keeping, and described how to use it (in my own words). Be sure to check out his articles, they are insightful to say the least.


After installing the stored procedure below called sp_AllocationMetaData, and allowing it to be executed from any database by  marking it as a system object, you can simply call this for a given table to extract a raw view of the page. Not entirely useful every day, but fun.

FirstName char(40),
LastName char(40) )

INSERT INTO Person VALUES ('Giles','Middleton')

EXEC sp_AllocationMetadata 'Person'

Which results in this bad boy:


The two underlined numbers are then fed into the DBCC PAGE tool

Notice that we pass in the database name, not the table name. We also have to enable a trace flag in order to see this output.


DBCC PAGE (‘test’, 1, 175, 3);

Et voilà – a memory dump!


As you can see, there is our data, and some extra bytes before and after it.

The first 4 bytes are meta information, followed by the data, then ended with 0x020000.

0x02 is actually little-endian and represents 0x0002, or 2 which is the number of columns.

The remaining byte represents a bitmask of nullable columns. We have none, so it’s a byte of zeros.


For more information on the data spewed out, see Paul’s other post.




Stored procedure – sp_AllocationMetadata

USE master;


IF OBJECT_ID (‘sp_AllocationMetadata’) IS NOT NULL
   DROP PROCEDURE sp_AllocationMetadata;


CREATE PROCEDURE sp_AllocationMetadata
@object VARCHAR (128) = NULL
OBJECT_NAME (sp.object_id) AS [Object Name],
sp.index_id AS [Index ID],
sa.allocation_unit_id AS [Alloc Unit ID],
sa.type_desc AS [Alloc Unit Type],
CONVERT (INT, SUBSTRING (sa.first_page, 6, 1) +
   SUBSTRING (sa.first_page, 5, 1))) +
CONVERT (INT, SUBSTRING (sa.first_page, 4, 1) +
   SUBSTRING (sa.first_page, 3, 1) +
SUBSTRING (sa.first_page, 2, 1) +
SUBSTRING (sa.first_page, 1, 1))) +
‘)’ AS [First Page],
   ‘(‘ CONVERT (VARCHAR (6),
SUBSTRING (sa.root_page, 6, 1) +
SUBSTRING (sa.root_page, 5, 1))) +
SUBSTRING (sa.root_page, 4, 1) +
SUBSTRING (sa.root_page, 3, 1) +
SUBSTRING (sa.root_page, 2, 1) +
SUBSTRING (sa.root_page, 1, 1))) +
‘)’ AS [Root Page],
SUBSTRING (sa.first_iam_page, 6, 1) +
SUBSTRING (sa.first_iam_page, 5, 1))) +
SUBSTRING (sa.first_iam_page, 4, 1) +
SUBSTRING (sa.first_iam_page, 3, 1) +
SUBSTRING (sa.first_iam_page, 2, 1) +
SUBSTRING (sa.first_iam_page, 1, 1))) +
‘)’ AS [First IAM Page]
sys.system_internals_allocation_units AS sa,
sys.partitions AS sp
sa.container_id = sp.partition_id
AND sp.object_id =
(CASE WHEN (@object IS NULL)
         THEN sp.object_id
ELSE OBJECT_ID (@object)

EXEC sys.sp_MS_marksystemobject sp_AllocationMetadata;





SQLServer Myth: NULL columns use no space


A table with NULL columns uses exactly the same amount of space as NOT NULL columns. Even indexes using NULL columns do not reduce.

If you really need to save space then the options are

Simply do not let a designer or developer insist on having a column exist in a table ‘just incase’ it is needed. Especially if that table is likely to store millions of records. Yes, “disk space is cheap”, but when a system is heavily used and critical – memory, backups, CPU, transfer times and network traffic start to matter. The more rows you can fit on a SQL page, the better.

Here’s the proof:
Create a new database called test, and run this SQL:
USE 'test'
CREATE TABLE tableNulls17SizeTest (
int1 INT NULL, int2 INT NULL, int3 INT NULL, int4 INT NULL, int5 INT NULL,
int6 INT NULL, int7 INT NULL, int8 INT NULL, int9 INT NULL, int10 INT NULL,
int11 INT NULL, int12 INT NULL, int13 INT NULL, int14 INT NULL, int15 INT NULL,
int16 INT NULL, int17 INT NULL )


INSERT INTO tableNulls17SizeTest VALUES(
GO 1000000

After 6 minutes….
sp_spaceused 'tableNulls17SizeTest'
SELECT page_count, record_count, avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(N'test'),
OBJECT_ID(N'tableNulls17SizeTest'), NULL, NULL, 'DETAILED')

Results in:


And if you check the file system, the .mdf file grows to 84mb.

Now, to test that the file is the same size with data, recreate the blank ‘test’ database, then execute this:

USE [test]

CREATE TABLE tableNoNulls17SizeTest (
int16 INT NOT NULL, int17 INT NOT NULL )
INSERT INTO tableNoNulls17SizeTest VALUES(
RAND()*10000000 )
GO 1000000

sp_spaceused ‘tableNoNulls17SizeTest’

SELECT page_count, record_count, avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats(DB_ID(N’test’),
OBJECT_ID(N’tableNoNulls17SizeTest’), NULL, NULL, ‘DETAILED’)

And the result….


I also tested the size of indexes with respect to nullable columns

CREATE NONCLUSTERED INDEX ix1 ON tableNulls17SizeTest ( int1,int2 )

CREATE NONCLUSTERED INDEX ix1 ON tableNoNulls17SizeTest ( int1,int2 )

And they had the same size on disk once built.