Posts Tagged ‘GPL’

Event Espresso and the GPL

There was quite a stir last week when theme developer, Jake Caputo, posted on his blog that he was disallowed from speaking or volunteering at his local WordCamp because he sells his themes on ThemeForest. If you’re interested in learning about the issue and the discussion, you can take a look at his post and the summary I wrote on my personal blog. This post isn’t going to be about whether or not Jake should be able to present at WordCamps.

We wanted to take a few minutes to talk about the GPL and how it applies to Event Espresso. I tend to be the resident GPL evangelist, so I was asked to be the one to write this post on how the GPL plays into what we do at Event Espresso.

What is the GPL?

GPL stands for Gnu Public License, and it is the software license under which WordPress is distributed. Briefly, it is an agreement between the software developer and the user about how the software can be used and what the expectations of the software may be. There are a few key points that are important to remember when discussing the GPL:

1. The GPL affects distribution.

The GPL license only affects code that you distribute to other parties. Writing code for a web site or client, that never gets released for public consumption beyond that site, does not need to have the GPL license attached to it.

2. The GPL does not include any warranty or guarantee of support.

In fact, the GPL explicitly states that the code might not even work at all!

3. The GPL grants the user (anyone with a copy of the code) the freedom to take, modify and/or redistribute the code.

This means you can take any GPL code and re-release it as you see fit, though you need to put your name on anything you change, so someone can get in touch with you if there are problems.

4. All WordPress plugins and themes must be released under a GPL-compatible license.

This does not mean that WordPress plugins and themes must be released under the GPL exclusively, nor does it mean that everything in a WordPress plugin or theme must be licensed with the GPL. Internal usage within an organization is totally free and not subject to any conditions. There is no such thing as ‘internal distribution’ that would restrict the usage of your code by requiring it to be GPL’d. It does mean that if you are releasing a WordPress plugin or theme for distribution, that it needs to be — in part or in whole — released under a GPL or compatible license.

What’s a “split-license”?

Matt posted a few days ago a comment in response to Japh, the WP Evangelist at ThemeForest, that there is “no such thing as a split-license”. I’ll therefore avoid perpetuating the misnomer, but clarify what the intended meaning is. A package that is distributed in which one license is applied to one part of the package (e.g. the php files) and another license is applied to another part of the package (e.g. images, css, javascript), has been commonly referred to as a “split-license”, which is what is currently in place on ThemeForest and CodeCanyon. It should be stated that there is absolutely nothing wrong with this — it does not violate the GPL in any way. However, as I point out in my blog post, the reason why it’s an issue when a ThemeForest theme developer volunteers for a WordCamp is because it violates the WordCamp guidelines that have been set out by the WordPress Foundation about who can (and can’t) be involved in the organizing of a WordCamp.

What does that mean for Event Espresso?

As a premium plugin developer, it’s a difficult position to be in. The GPL makes it so anyone can get a copy of your plugin and resell it, or just provide a link to a full version of a piece of software that — in our case — has been the product of literally tens of thousands of hours of development. This is why, when you purchase Event Espresso, you are not buying the code.  You are paying for support and updates for the length of the license — the very things that the GPL implicitly does not provide. People are always finding ways to pirate software, and WordPress themes and plugins are no different. However, as I always like to say, good luck getting support. With Event Espresso, if you found a copy online (outside of our site) you would not be able to access the forums except for the free forums or the translator forums (where it would become obvious pretty quickly that you were not using the free version or had a question relating to the translations based on your version and your questions) and only limited access to our support documentation. And you would have no access to updates of any kind.

We are proud of our dedication to open source software. We are actively seeking new partnerships with other WordPress developers, and the API we’re developing will expand Event Espresso events to sites that don’t even run on WordPress. If you have questions about the GPL, take a look at the Frequently Asked Questions on Gnu.org or feel free to contact me on Twitter — I love talking about the GPL helping people understand what it is and how it works!

Tags: , , ,
Posted in Product & News | No Comments »

Event Espresso
[gravityform id=116 title=false description=false]
<script type="text/javascript">var gform;gform||(document.addEventListener("gform_main_scripts_loaded",function(){gform.scriptsLoaded=!0}),window.addEventListener("DOMContentLoaded",function(){gform.domLoaded=!0}),gform={domLoaded:!1,scriptsLoaded:!1,initializeOnLoaded:function(o){gform.domLoaded&&gform.scriptsLoaded?o():!gform.domLoaded&&gform.scriptsLoaded?window.addEventListener("DOMContentLoaded",o):document.addEventListener("gform_main_scripts_loaded",o)},hooks:{action:{},filter:{}},addAction:function(o,n,r,t){gform.addHook("action",o,n,r,t)},addFilter:function(o,n,r,t){gform.addHook("filter",o,n,r,t)},doAction:function(o){gform.doHook("action",o,arguments)},applyFilters:function(o){return gform.doHook("filter",o,arguments)},removeAction:function(o,n){gform.removeHook("action",o,n)},removeFilter:function(o,n,r){gform.removeHook("filter",o,n,r)},addHook:function(o,n,r,t,i){null==gform.hooks[o][n]&&(gform.hooks[o][n]=[]);var e=gform.hooks[o][n];null==i&&(i=n+"_"+e.length),gform.hooks[o][n].push({tag:i,callable:r,priority:t=null==t?10:t})},doHook:function(n,o,r){var t;if(r=Array.prototype.slice.call(r,1),null!=gform.hooks[n][o]&&((o=gform.hooks[n][o]).sort(function(o,n){return o.priority-n.priority}),o.forEach(function(o){"function"!=typeof(t=o.callable)&&(t=window[t]),"action"==n?t.apply(null,r):r[0]=t.apply(null,r)})),"filter"==n)return r[0]},removeHook:function(o,n,t,i){var r;null!=gform.hooks[o][n]&&(r=(r=gform.hooks[o][n]).filter(function(o,n,r){return!!(null!=i&&i!=o.tag||null!=t&&t!=o.priority)}),gform.hooks[o][n]=r)}});</script> <div class='gf_browser_unknown gform_wrapper gform_legacy_markup_wrapper' id='gform_wrapper_116' ><form method='post' enctype='multipart/form-data' id='gform_116' action='/tag/gpl/' novalidate> <div class='gform_body gform-body'><ul id='gform_fields_116' class='gform_fields top_label form_sublabel_below description_below'><li id="field_116_5" class="gfield gfield_contains_required field_sublabel_hidden_label field_description_below gfield_visibility_visible" ><label class='gfield_label gfield_label_before_complex' >What is your first name?<span class="gfield_required"><span class="gfield_required gfield_required_asterisk">*</span></span></label><div class='ginput_complex ginput_container no_prefix has_first_name no_middle_name no_last_name no_suffix gf_name_has_1 ginput_container_name' id='input_116_5'> <span id='input_116_5_3_container' class='name_first' > <input type='text' name='input_5.3' id='input_116_5_3' value='' aria-required='true' placeholder='First name' /> <label for='input_116_5_3' class='hidden_sub_label screen-reader-text'>First name</label> </span> </div></li><li id="field_116_1" class="gfield gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible" ><label class='gfield_label' for='input_116_1' >What is your email address so we can follow up with you?<span class="gfield_required"><span class="gfield_required gfield_required_asterisk">*</span></span></label><div class='ginput_container ginput_container_text'><input name='input_1' id='input_116_1' type='text' value='' class='medium' placeholder='hello@example.com' aria-required="true" aria-invalid="false" /> </div></li><li id="field_116_2" class="gfield gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible" ><label class='gfield_label' for='input_116_2' >Tell us about your concerns below<span class="gfield_required"><span class="gfield_required gfield_required_asterisk">*</span></span></label><div class='ginput_container ginput_container_textarea'><textarea name='input_2' id='input_116_2' class='textarea medium' placeholder='What kind of events are you planning?' aria-required="true" aria-invalid="false" rows='10' cols='50'></textarea></div></li><li id="field_116_6" class="gfield field_sublabel_below field_description_below gfield_visibility_visible" ><label class='gfield_label gfield_label_before_complex' >GDPR Agreement</label><div class='ginput_container ginput_container_checkbox'><ul class='gfield_checkbox' id='input_116_6'><li class='gchoice gchoice_116_6_1'> <input class='gfield-choice-input' name='input_6.1' type='checkbox' value='I consent to have this website store my submitted information so they can respond to my inquiry.' id='choice_116_6_1' /> <label for='choice_116_6_1' id='label_116_6_1'>I consent to have this website store my submitted information so they can respond to my inquiry.</label> </li></ul></div></li><li id="field_116_3" class="gfield gform_hidden field_sublabel_below field_description_below gfield_visibility_visible" ><div class='ginput_container ginput_container_text'><input name='input_3' id='input_116_3' type='hidden' class='gform_hidden' aria-invalid="false" value='' /></div></li><li id="field_116_4" class="gfield gform_hidden field_sublabel_below field_description_below gfield_visibility_visible" ><div class='ginput_container ginput_container_text'><input name='input_4' id='input_116_4' type='hidden' class='gform_hidden' aria-invalid="false" value='https://eventespresso.com/tag/gpl/' /></div></li><li id="field_116_7" class="gfield gform_validation_container field_sublabel_below field_description_below gfield_visibility_visible" ><label class='gfield_label' for='input_116_7' >Email</label><div class='ginput_container'><input name='input_7' id='input_116_7' type='text' value='' autocomplete='new-password'/></div><div class='gfield_description' id='gfield_description_116_7'>This field is for validation purposes and should be left unchanged.</div></li></ul></div> <div class='gform_footer top_label'> <input type='submit' id='gform_submit_button_116' class='gform_button button' value='Send my message' onclick='if(window["gf_submitting_116"]){return false;} if( !jQuery("#gform_116")[0].checkValidity || jQuery("#gform_116")[0].checkValidity()){window["gf_submitting_116"]=true;} ' onkeypress='if( event.keyCode == 13 ){ if(window["gf_submitting_116"]){return false;} if( !jQuery("#gform_116")[0].checkValidity || jQuery("#gform_116")[0].checkValidity()){window["gf_submitting_116"]=true;} jQuery("#gform_116").trigger("submit",[true]); }' /> <input type='hidden' class='gform_hidden' name='is_submit_116' value='1' /> <input type='hidden' class='gform_hidden' name='gform_submit' value='116' /> <input type='hidden' class='gform_hidden' name='gform_unique_id' value='' /> <input type='hidden' class='gform_hidden' name='state_116' value='WyJbXSIsIjBiNjdjZjkyMDUzOWUxOWY5Y2NiZjIwMzM4YjA1Mjk4Il0=' /> <input type='hidden' class='gform_hidden' name='gform_target_page_number_116' id='gform_target_page_number_116' value='0' /> <input type='hidden' class='gform_hidden' name='gform_source_page_number_116' id='gform_source_page_number_116' value='1' /> <input type='hidden' name='gform_field_values' value='' /> </div> <p style="display: none !important;"><label>&#916;<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_1" name="ak_js" value="35"/><script>document.getElementById( "ak_js_1" ).setAttribute( "value", ( new Date() ).getTime() );</script></p></form> </div>