Revision: 1528
http://mrbs.svn.sourceforge.net/mrbs/?rev=1528&view=rev
Author: cimorrison
Date: 2010-10-21 17:02:54 +0000 (Thu, 21 Oct 2010)
Log Message:
-----------
Merged in latest changes from the trunk
Modified Paths:
--------------
mrbs/branches/from_to_bookings/INSTALL
mrbs/branches/from_to_bookings/web/Themes/default/header.inc
mrbs/branches/from_to_bookings/web/edit_area_room.php
mrbs/branches/from_to_bookings/web/edit_entry.php
mrbs/branches/from_to_bookings/web/edit_entry_handler.php
mrbs/branches/from_to_bookings/web/functions.inc
mrbs/branches/from_to_bookings/web/functions_mail.inc
mrbs/branches/from_to_bookings/web/lang.en
mrbs/branches/from_to_bookings/web/mrbs-ie8.css
mrbs/branches/from_to_bookings/web/mrbs.css.php
mrbs/branches/from_to_bookings/web/session_cookie.inc
mrbs/branches/from_to_bookings/web/session_php.inc
mrbs/branches/from_to_bookings/web/systemdefaults.inc.php
Property Changed:
----------------
mrbs/branches/from_to_bookings/
mrbs/branches/from_to_bookings/web/upgrade/5/pgsql.sql
Property changes on: mrbs/branches/from_to_bookings
___________________________________________________________________
Modified: svn:mergeinfo
- /mrbs/branches/custom_entry_fields:1374-1396
/mrbs/branches/datepicker:1409-1416
/mrbs/branches/improve_css_2008_06:804-872
/mrbs/branches/provisional_bookings:1242-1280
+ /mrbs/branches/custom_entry_fields:1374-1396
/mrbs/branches/datepicker:1409-1416
/mrbs/branches/improve_css_2008_06:804-872
/mrbs/branches/provisional_bookings:1242-1280
/mrbs/trunk:1491-1527
Modified: mrbs/branches/from_to_bookings/INSTALL
===================================================================
--- mrbs/branches/from_to_bookings/INSTALL 2010-10-21 16:49:27 UTC (rev
1527)
+++ mrbs/branches/from_to_bookings/INSTALL 2010-10-21 17:02:54 UTC (rev
1528)
@@ -206,6 +206,44 @@
should then do the rest and display your coffee machine field on the room
pages.
+Extra options for custom fields:
+
+1)
+
+You can create dropdown boxes for a custom field by defining an
+entry in the configuration array $select_options. For example:
+
+$select_options['entry.conference_facilities'] = array('Video',
+ 'Telephone',
+ 'None');
+
+would define the 'conference_facilities' custom field to have three
+possible values.
+
+2)
+
+You can specify that a field is mandatory. This will ensure that the
+user specifies a value for a field that may be empty, like a text box
+or a selection, as in 1) above. For example:
+
+$is_mandatory_field['entry.conference_facilities'] = true;
+
+would define the 'conference_facilities' custom field to be mandatory.
+In the case of a select field, this adds an empty value to the dropdown
+list.
+
+3)
+
+You can also specify that a field is private, ensuring that the contents
+are only visible to yourself and the administrators. For example:
+
+$is_private_field['entry.refreshments'] = true;
+
+would prevent the details of your refreshments being visible to other
+users - provided that private bookings are enabled. See the section
+on private bookings in systemdefaults.inc.php for more information.
+
+
Technical explanation of the restriction on column names for custom fields
--------------------------------------------------------------------------
// Column names for custom fields are used by MRBS in a number of ways:
Modified: mrbs/branches/from_to_bookings/web/Themes/default/header.inc
===================================================================
--- mrbs/branches/from_to_bookings/web/Themes/default/header.inc
2010-10-21 16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/Themes/default/header.inc
2010-10-21 17:02:54 UTC (rev 1528)
@@ -80,7 +80,10 @@
// changed and the regional setting stays as it was before. The reverse
order
// of priority is:
// - the MRBS default language
- // - locales taken from the browser in increasing order of browser preference
+ // - locales taken from the browser in increasing order of browser
preference,
+ // taking for each locale
+ // - the language part only (in case the xx-YY localisation does not
exist)
+ // - the full locale
// - then, if automatic language changing is disabled,
// - the MRBS default language setting again
// - the language part of the override_locale
@@ -110,6 +113,13 @@
// Get the locale in the format that datepicker likes: language lower case
// and country upper case (xx-XX)
$datepicker_locale = locale_format($lang, '-');
+ // First we'll try and get the correct language and then we'll try and
+ // overwrite that with the correct country variant
+ if (strlen($datepicker_locale) > 2)
+ {
+ $datepicker_lang = substr($datepicker_locale, 0, 2);
+ echo
"$.datepicker.setDefaults($.datepicker.regional['$datepicker_lang']);\n";
+ }
echo
"$.datepicker.setDefaults($.datepicker.regional['$datepicker_locale']);\n";
}
if ($disable_automatic_language_changing)
Modified: mrbs/branches/from_to_bookings/web/edit_area_room.php
===================================================================
--- mrbs/branches/from_to_bookings/web/edit_area_room.php 2010-10-21
16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/edit_area_room.php 2010-10-21
17:02:54 UTC (rev 1528)
@@ -152,11 +152,17 @@
exit();
}
}
+
+ require_once "functions_mail.inc";
// PHASE 2 (ROOM) - UPDATE THE DATABASE
// ------------------------------------
if (isset($change_room) && !empty($room))
{
+ // clean up the address list replacing newlines by commas and removing
duplicates
+ $room_admin_email = clean_address_list($room_admin_email);
+ // put a space after each comma so that the list displays better
+ $room_admin_email = str_replace(',', ', ', $room_admin_email);
// validate the email addresses
$valid_email = validate_email_list($room_admin_email);
@@ -267,6 +273,10 @@
if (isset($change_area) && !empty($area))
{
+ // clean up the address list replacing newlines by commas and removing
duplicates
+ $area_admin_email = clean_address_list($area_admin_email);
+ // put a space after each comma so that the list displays better
+ $area_admin_email = str_replace(',', ', ', $area_admin_email);
// validate email addresses
$valid_email = validate_email_list($area_admin_email);
@@ -500,15 +510,15 @@
echo "<input type=\"text\" id=\"capacity\" name=\"capacity\"
value=\"" . $row["capacity"] . "\"$disabled>\n";
break;
case 'room_admin_email':
- echo "<label for=\"room_admin_email\">" .
get_vocab("room_admin_email") . ":</label>\n";
- echo "<input type=\"text\" id=\"room_admin_email\"
name=\"room_admin_email\" maxlength=\"75\" value=\"" .
htmlspecialchars($row["room_admin_email"]) . "\"$disabled>\n";
+ echo "<label for=\"room_admin_email\" title=\"" .
get_vocab("email_list_note") . "\">" . get_vocab("room_admin_email") .
":</label>\n";
+ echo "<textarea id=\"room_admin_email\"
name=\"room_admin_email\" rows=\"4\" cols=\"40\"$disabled>" .
htmlspecialchars($row["room_admin_email"]) . "</textarea>\n";
break;
case 'custom_html':
if ($is_admin)
{
// Only show the raw HTML to admins. Non-admins will see the
rendered HTML
echo "<label for=\"room_custom_html\" title=\"" .
get_vocab("custom_html_note") . "\">" . get_vocab("custom_html") .
":</label>\n";
- echo "<textarea id=\"room_custom_html\" class=\"custom_html\"
name=\"custom_html\" rows=\"4\" cols=\"40\"$disabled>\n";
+ echo "<textarea id=\"room_custom_html\" name=\"custom_html\"
rows=\"4\" cols=\"40\"$disabled>\n";
echo htmlspecialchars($row['custom_html']);
echo "</textarea>\n";
}
@@ -639,15 +649,17 @@
</div>
<div>
- <label for="area_admin_email"><?php echo get_vocab("area_admin_email")
?>:</label>
- <input type="text" id="area_admin_email" name="area_admin_email"
maxlength="75" value="<?php echo htmlspecialchars($row["area_admin_email"]);
?>">
+ <?php
+ echo "<label for=\"area_admin_email\" title=\"" .
get_vocab("email_list_note") . "\">" . get_vocab("area_admin_email") .
":</label>\n";
+ ?>
+ <textarea id="area_admin_email" name="area_admin_email" rows="4"
cols="40"><?php echo htmlspecialchars($row["area_admin_email"]); ?></textarea>
</div>
<?php
// The custom HTML
echo "<div>\n";
echo "<label for=\"area_custom_html\" title=\"" .
get_vocab("custom_html_note") . "\">" . get_vocab("custom_html") .
":</label>\n";
- echo "<textarea id=\"area_custom_html\" class=\"custom_html\"
name=\"custom_html\" rows=\"4\" cols=\"40\">\n";
+ echo "<textarea id=\"area_custom_html\" name=\"custom_html\"
rows=\"4\" cols=\"40\">\n";
echo htmlspecialchars($row['custom_html']);
echo "</textarea>\n";
echo "</div>\n";
Modified: mrbs/branches/from_to_bookings/web/edit_entry.php
===================================================================
--- mrbs/branches/from_to_bookings/web/edit_entry.php 2010-10-21 16:49:27 UTC
(rev 1527)
+++ mrbs/branches/from_to_bookings/web/edit_entry.php 2010-10-21 17:02:54 UTC
(rev 1528)
@@ -456,7 +456,49 @@
alert("<?php echo get_vocab("you_have_not_selected") . '\n' .
get_vocab("valid_room") ?>");
return false;
}
+
+ <?php
+ if (count($is_mandatory_field))
+ {
+ $m_fields = array();
+ foreach ($is_mandatory_field as $field => $value)
+ {
+ if ($value)
+ {
+ $field = preg_replace('/^entry\./', 'f_', $field);
+ $m_fields[] = "'".str_replace("'", "\\'", $field)."'";
+ }
+ }
+ echo "var mandatory_fields = [".implode(', ', $m_fields)."];\n";
+ ?>
+ var return_val = true;
+
+ $.each(mandatory_fields,
+ function(index, value)
+ {
+ if ($("#"+value).val() == '')
+ {
+ label = $("label[for="+value+"]").html();
+ label = label.replace(/:$/, '');
+ alert('"' + label + '" ' +
+ <?php echo '"'.
+ str_replace('"', '\\"',
+ get_vocab("is_mandatory_field")
+ ).
+ '"'; ?>);
+ return_val = false;
+ }
+ });
+ if (!return_val)
+ {
+ return return_val;
+ }
+ <?php
+
+ }
+ ?>
+
// Form submit can take some times, especially if mails are enabled and
// there are more than one recipient. To avoid users doing weird things
// like clicking more than one time on submit button, we hide it as soon
@@ -819,7 +861,10 @@
// Output a select box if they want one
elseif (count($select_options["entry.$key"]) > 0)
{
- generate_select($label_text, $var_name, $value,
$select_options["entry.$key"]);
+ $mandatory = (array_key_exists("entry.$key", $is_mandatory_field) &&
+ $is_mandatory_field["entry.$key"]) ? true : false;
+ generate_select($label_text, $var_name, $value,
+ $select_options["entry.$key"], $mandatory);
}
// Output a textarea if it's a character string longer than the limit
for a
// text input
Modified: mrbs/branches/from_to_bookings/web/edit_entry_handler.php
===================================================================
--- mrbs/branches/from_to_bookings/web/edit_entry_handler.php 2010-10-21
16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/edit_entry_handler.php 2010-10-21
17:02:54 UTC (rev 1528)
@@ -230,6 +230,28 @@
print_footer(TRUE);
}
+if (count($is_mandatory_field))
+{
+ foreach ($is_mandatory_field as $field => $value)
+ {
+ $field = preg_replace('/^entry\./', '', $field);
+ if ($value && ($custom_fields[$field] == ''))
+ {
+ print_header($day, $month, $year, $area, isset($room) ? $room : "");
+?>
+ <h1><?php echo get_vocab('invalid_booking'); ?></h1>
+ <p>
+ <?php echo get_vocab('missing_mandatory_field')." \"".
+ get_loc_field_name($tbl_entry, $field)."\""; ?>
+ </p>
+<?php
+ // Print footer and exit
+ print_footer(TRUE);
+ }
+ }
+}
+
+
if ($enable_periods)
{
$resolution = 60;
Modified: mrbs/branches/from_to_bookings/web/functions.inc
===================================================================
--- mrbs/branches/from_to_bookings/web/functions.inc 2010-10-21 16:49:27 UTC
(rev 1527)
+++ mrbs/branches/from_to_bookings/web/functions.inc 2010-10-21 17:02:54 UTC
(rev 1528)
@@ -315,11 +315,16 @@
}
// Generates a select box from $options, an array of options
-function generate_select($label_text, $name, $value, $options)
+function generate_select($label_text, $name, $value, $options,
+ $mandatory = false)
{
// generate the HTML
$html = "<label for=\"$name\">$label_text</label>\n";
$html .= "<select id=\"$name\" name=\"$name\">\n";
+ if ($mandatory)
+ {
+ $options = array_merge(array(""),$options);
+ }
foreach ($options as $option)
{
$html .= "<option";
Modified: mrbs/branches/from_to_bookings/web/functions_mail.inc
===================================================================
--- mrbs/branches/from_to_bookings/web/functions_mail.inc 2010-10-21
16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/functions_mail.inc 2010-10-21
17:02:54 UTC (rev 1528)
@@ -165,15 +165,33 @@
// some of the elements of the original array may themselves have
// been comma separated strings
$array = explode(',', $string);
- // remove any leading and trailing whitespace
- array_walk($array, 'trim');
+ // remove any leading and trailing whitespace and any empty strings
+ $trimmed_array = array();
+ for ($i=0; $i < count($array); $i++)
+ {
+ $array[$i] = trim($array[$i]);
+ if ($array[$i] != '')
+ {
+ $trimmed_array[] = $array[$i];
+ }
+ }
// remove duplicates
- $array = array_unique($array);
+ $trimmed_array = array_unique($trimmed_array);
// re-assemble the string
- $string = implode(',', $array);
+ $string = implode(',', $trimmed_array);
return $string;
}
+// Take a string of email addresses separated by commas or newlines
+// and return a comma separated list with duplicates removed.
+function clean_address_list($string)
+{
+ $string = str_replace(array("\r\n", "\n", "\r"), ',', $string);
+ $array = explode(',', $string);
+ $string = get_address_list($array);
+ return $string;
+}
+
// get the email address of a user
// returns an empty string in the event of an error
function get_email_address($user)
@@ -530,8 +548,8 @@
// Created by
$body .= "\n" . get_mail_vocab("createdby") . ": " .
- compareEntries($create_by,
- $mail_previous['createdby'],
+ compareEntries(convertToMailCharset($create_by),
+ convertToMailCharset($mail_previous['createdby']),
$new_entry) . "\n";
// Custom fields
@@ -553,7 +571,9 @@
}
}
$body .= get_mail_field_name($tbl_entry, $key) . ": ";
- $body .= compareEntries($value, $mail_previous[$key], $new_entry) .
"\n";
+ $body .= compareEntries(convertToMailCharset($value),
+ convertToMailCharset($mail_previous[$key]),
+ $new_entry) . "\n";
}
}
Modified: mrbs/branches/from_to_bookings/web/lang.en
===================================================================
--- mrbs/branches/from_to_bookings/web/lang.en 2010-10-21 16:49:27 UTC (rev
1527)
+++ mrbs/branches/from_to_bookings/web/lang.en 2010-10-21 17:02:54 UTC (rev
1528)
@@ -95,6 +95,8 @@
$vocab["useful_n-weekly_value"] = "useful n-weekly value.";
$vocab["private"] = "Private";
$vocab["unavailable"] = "Private";
+$vocab["is_mandatory_field"] = "is a mandatory field, please supply a value";
+$vocab["missing_mandatory_field"] = "You have not supplied a value for the
mandatory field";
$vocab["start_after_end"] = "Start day after end day";
$vocab["start_after_end_long"] = "Error: the start day is after the end day";
@@ -341,6 +343,7 @@
$vocab["max_book_ahead"] = "Advance booking - maximum";
$vocab["custom_html"] = "Custom HTML";
$vocab["custom_html_note"] = "This field can be used for displaying
your own HTML, for example an embedded Google map";
+$vocab["email_list_note"] = "Enter a list of email addresses separated
by commas or newlines";
// Used in edit_users.php
Modified: mrbs/branches/from_to_bookings/web/mrbs-ie8.css
===================================================================
--- mrbs/branches/from_to_bookings/web/mrbs-ie8.css 2010-10-21 16:49:27 UTC
(rev 1527)
+++ mrbs/branches/from_to_bookings/web/mrbs-ie8.css 2010-10-21 17:02:54 UTC
(rev 1528)
@@ -9,6 +9,7 @@
/* set it to visible explicitly for the y direction */
.form_general label {overflow-y: visible}
.form_general #ad label {overflow-y: auto} /* undo for all-day checkbox */
+.edit_area_room div.group {width: 25em} /* not necessary in IE7 or IE9 ?! */
/* ------------ TRAILER.INC ---------------------*/
Modified: mrbs/branches/from_to_bookings/web/mrbs.css.php
===================================================================
--- mrbs/branches/from_to_bookings/web/mrbs.css.php 2010-10-21 16:49:27 UTC
(rev 1527)
+++ mrbs/branches/from_to_bookings/web/mrbs.css.php 2010-10-21 17:02:54 UTC
(rev 1528)
@@ -455,7 +455,7 @@
.edit_area_room .form_general fieldset fieldset {padding-top: 0.5em;
padding-bottom: 0.5em}
.edit_area_room .form_general fieldset fieldset legend {font-size: small;
font-style: italic; font-weight: normal}
span#private_display_caution {display: block; margin-top: 1em; font-style:
italic; font-weight: normal}
-.edit_area_room textarea.custom_html {height: 6em; width: 25em}
+.edit_area_room .form_general textarea {height: 6em; width: 25em}
.edit_area_room div#custom_html {margin-top: 8px}
@@ -544,7 +544,7 @@
#logon label {max-width: <?php echo
$logon_left_col_max_width ?>em}
#db_logon label {max-width: <?php echo
$db_logon_left_col_max_width ?>em}
-.form_general .group label {clear: none; width: auto; max-width: 100%;
font-weight: normal; overflow: visible}
+.form_general .group label {clear: none; width: auto; max-width: 100%;
font-weight: normal; overflow: visible; text-align: left}
.form_general input {
display: block; float: left; margin-left: <?php echo $general_gap ?>em;
@@ -567,7 +567,7 @@
font-family: <?php echo $standard_font_family ?>; font-size: small
}
.form_general select {float: left; margin-left: <?php echo $general_gap ?>em;
margin-right: -0.5em; margin-bottom: 0.5em}
-.form_general input.radio {margin-top: 0.1em}
+.form_general input.radio {margin-top: 0.1em; margin-right: 2px}
.form_general input.checkbox {width: auto; margin-top: 0.2em}
.edit_area_room .form_general input.checkbox {margin-left: <?php echo
$general_gap ?>em}
.edit_area_room .form_general #booking_policies input.text {width: 2.0em}
Modified: mrbs/branches/from_to_bookings/web/session_cookie.inc
===================================================================
--- mrbs/branches/from_to_bookings/web/session_cookie.inc 2010-10-21
16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/session_cookie.inc 2010-10-21
17:02:54 UTC (rev 1528)
@@ -41,7 +41,7 @@
{
$cookie_path = $PHP_SELF;
// Strip off everything after the last '/' in $PHP_SELF
- $cookie_path = preg_replace('/[^/]*$/', '', $cookie_path);
+ $cookie_path = preg_replace('/[^\/]*$/', '', $cookie_path);
}
/* Delete old-style cookies */
@@ -82,7 +82,14 @@
$UserPassword = $NewUserPassword;
}
- $expiry_time = time()+$auth['session_cookie']['session_expire_time'];
+ if ($auth['session_cookie']['session_expire_time'] == 0)
+ {
+ $expiry_time = 0;
+ }
+ else
+ {
+ $expiry_time = time()+$auth['session_cookie']['session_expire_time'];
+ }
$token = "AUTH".$UserName."|".$expiry_time;
if ($auth['session_cookie']['include_ip'])
{
@@ -196,7 +203,7 @@
function getUserName()
{
- global $blowfish, $REMOTE_ADDR;
+ global $blowfish, $REMOTE_ADDR, $auth;
$encrypted_token = NULL;
$username = NULL;
@@ -227,9 +234,11 @@
/* Check for a valid token */
if (isset($parts[0]) &&
- isset($parts[1]) && ($parts[1] > time()) &&
+ isset($parts[1]) &&
+ ((($auth["session_cookie"]["session_expire_time"] == 0) &&
+ ($parts[1] == 0)) || ($parts[1] > time())) &&
(!isset($parts[2]) ||
- (isset($parts[2]) && ($parts[2] == $REMOTE_ADDR))))
+ (isset($parts[2]) && ($parts[2] == $REMOTE_ADDR))))
{
$username = $parts[0];
}
Modified: mrbs/branches/from_to_bookings/web/session_php.inc
===================================================================
--- mrbs/branches/from_to_bookings/web/session_php.inc 2010-10-21 16:49:27 UTC
(rev 1527)
+++ mrbs/branches/from_to_bookings/web/session_php.inc 2010-10-21 17:02:54 UTC
(rev 1528)
@@ -35,7 +35,7 @@
{
$cookie_path = $PHP_SELF;
// Strip off everything after the last '/' in $PHP_SELF
- $cookie_path = preg_replace('/[^/]*$/', '', $cookie_path);
+ $cookie_path = preg_replace('/[^\/]*$/', '', $cookie_path);
}
global $auth;
@@ -47,9 +47,9 @@
$auth["session_php"]["session_expire_time"] = 0;
}
+session_name("MRBS_SESSID"); // call before session_set_cookie_params() - see
PHP manual
session_set_cookie_params($auth["session_php"]["session_expire_time"],
$cookie_path);
-session_name("MRBS_SESSID");
session_start();
/*
Modified: mrbs/branches/from_to_bookings/web/systemdefaults.inc.php
===================================================================
--- mrbs/branches/from_to_bookings/web/systemdefaults.inc.php 2010-10-21
16:49:27 UTC (rev 1527)
+++ mrbs/branches/from_to_bookings/web/systemdefaults.inc.php 2010-10-21
17:02:54 UTC (rev 1528)
@@ -499,7 +499,11 @@
// - Entry table: name, description and custom fields
// - Users table: custom fields
+// You can define custom entry fields to be mandatory by setting
+// items in the array $is_mandatory_field. For example:
+// $is_mandatory_field['entry.coffee_required'] = true;
+
/***********************************************
* Authentication settings - read AUTHENTICATION
@@ -518,7 +522,7 @@
// The encryption secret key for the session tokens. You are strongly
// advised to change this if you use this session scheme
$auth["session_cookie"]["secret"] = "This isn't a very good secret!";
-// The expiry time of a session, in seconds
+// The expiry time of a session, in seconds. Set to 0 to use session cookies
$auth["session_cookie"]["session_expire_time"] = (60*60*24*30); // 30 days
// Whether to include the user's IP address in their session cookie.
// Increases security, but could cause problems with proxies/dynamic IP
@@ -538,7 +542,7 @@
// Cookie path override. If this value is set it will be used by the
// 'php' and 'cookie' session schemes to override the default behaviour
// of automatically determining the cookie path to use
-$cookie_path_override = '';
+//$cookie_path_override = '/mrbs/';
// The list of administrators (can modify other peoples settings).
//
Property changes on: mrbs/branches/from_to_bookings/web/upgrade/5/pgsql.sql
___________________________________________________________________
Modified: svn:mergeinfo
- /mrbs/branches/custom_entry_fields/web/upgrade/5/pgsql.sql:1374-1396
/mrbs/branches/datepicker/web/upgrade/5/pgsql.sql:1409-1416
/mrbs/branches/provisional_bookings/web/upgrade/5/pgsql.sql:1242-1280
+ /mrbs/branches/custom_entry_fields/web/upgrade/5/pgsql.sql:1374-1396
/mrbs/branches/datepicker/web/upgrade/5/pgsql.sql:1409-1416
/mrbs/branches/provisional_bookings/web/upgrade/5/pgsql.sql:1242-1280
/mrbs/trunk/web/upgrade/5/pgsql.sql:1491-1527
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
Mrbs-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mrbs-commits