*/ include('../../.htpasswd'); //Connect to to database $con = mysqli_connect($host, $username_rw, $pass_rw, $db_name); //Set encoding options mysqli_set_charset($con, 'utf-8'); header('Content-Type: text/html; charset=utf8'); mysqli_query($con, 'SET NAMES utf8;'); //Return the db connection return $con; } /**************************************************** * Gives the version of one or more of the sections * * of the database, or the global section. * * * * @params: * * con: (MySQL server connection) RO mode enough. * * section: (string): 'blog', 'activities', * * 'gallery', 'lablanca', 'global'. None * * to get them all. * * @return: (int): The version of the db section. * ****************************************************/ function get_version($con, $section = SEC_ALL){ if ($section == SEC_ALL){ $q = mysqli_query($con, "SELECT SUM(version) AS version FROM version;"); } else{ $q = mysqli_query($con, "SELECT version FROM version WHERE section = '$section';"); } if (mysqli_num_rows($q) == 0){ //'Bad request' status code http_response_code(400); return 0; } else{ $r = mysqli_fetch_array($q); return($r['version']); } } /**************************************************** * Gives the version of every section of the db. * * * * @params: * * con: (MySQL server connection) RO mode enough. * * @return: (Assoc. array): The versions of the db. * ****************************************************/ function get_all_versions($con){ $v = array(); $v[] = [SEC_ALL => get_version($con, SEC_ALL)]; $v[] = [SEC_BLOG => get_version($con, SEC_BLOG)]; $v[] = [SEC_ACTIVITIES => get_version($con, SEC_ACTIVITIES)]; $v[] = [SEC_GALLERY => get_version($con, SEC_GALLERY)]; $v[] = [SEC_LABLANCA => get_version($con, SEC_LABLANCA)]; return $v; } /**************************************************** * Prepares the info of the database or a portion of * * it in the selected format. * * * * @params: * * con: (MySQL server connection) RO mode enough. * * section: (string): 'blog', 'activities', * * 'gallery', 'lablanca', 'global'. None * * to get them all. * * format: (int): 1: json (default). * * @return: (String): data in the desired format. * ****************************************************/ function sync($con, $section = SEC_ALL, $format = DEF_FORMAT){ switch ($section){ case SEC_BLOG: $tables = [ 'post', 'post_comment', 'post_image', 'post_tag' ]; break; case SEC_ACTIVITIES: $tables = [ 'activity', 'activity_itinerary', 'activity_comment', 'activity_image', 'activity_tag', 'activity_itinerary', 'location', 'album', 'photo', 'photo_album', 'photo_comment', 'place' ]; break; case SEC_GALLERY: $tables = [ 'album', 'photo', 'photo_album', 'photo_comment', 'place' ]; break; case SEC_LABLANCA: $tables = [ 'festival', 'festival_day', 'festival_event', 'festival_event_image', 'festival_offer', 'place', 'people' ]; break; case SEC_ALL: $tables = [ 'activity', 'activity_itinerary', 'activity_comment', 'activity_image', 'activity_tag', 'album', 'photo', 'festival', 'festival_day', 'festival_event', 'festival_event_image', 'festival_offer', 'photo_album', 'place', 'people', 'post', 'post_comment', 'post_image', 'post_tag', 'settings', 'sponsor' ]; break; default: //'Bad request' staus code http_response_code(400); return; } $v = array(); if ($section == SEC_ALL){ $v = get_all_versions($con); } else{ $v[] = [ $section => get_version($con, $section) ]; } switch ($format){ case FOR_JSON: $db = array(); foreach($tables as $table){ $req_table = get_table($con, $table, $format); if ($req_table != -1){ $db[] = [ $table => $req_table]; } } $data = array(); $data[] = [ KEY_VERSION => $v ]; $data[] = [ KEY_DATA => $db]; return(json_encode($data)); break; } } /**************************************************** * Echoes the contents of a table from the database. * * Inaccessible or sensitive tables or fields are * * not printed. * * * * @params: * * con: (MySQL server connection) RO mode enough. * * table (string): The name of the table. * * @return: (Assoc Array): Data in the table. * ****************************************************/ function get_table($con, $table){ $table = strtolower($table); switch ($table){ case "activity": $q = mysqli_query($con, "SELECT id, permalink, date, city, title_es, title_en, title_eu, text_es, text_eu, text_en, after_es, after_en, after_eu, price, inscription, max_people, album FROM activity WHERE visible = 1;"); break; case "activity_comment": $q = mysqli_query($con, "SELECT id, activity, text, dtime, username, lang FROM activity_comment WHERE approved = 1;"); break; case "album": $q = mysqli_query($con, "SELECT id, permalink, title_es, title_en, title_eu, description_es, description_en, description_eu, open FROM album;"); break; case "photo": $q = mysqli_query($con, "SELECT photo.id AS id, file, permalink, title_es, title_en, title_eu, description_es, description_en, description_eu, uploaded, place, width, height, size, CONCAT(photo.username, user) AS username FROM photo, user WHERE user.id = photo.user AND approved = 1;"); break; case "post": $q = mysqli_query($con, "SELECT post.id AS id, permalink, title_es, title_en, title_eu, text_es, text_en, text_eu, comments, username, dtime FROM post, user WHERE user.id = user AND visible = 1;"); break; case "post_comment": $q = mysqli_query($con, "SELECT post_comment.id AS id, post, text, dtime, username, lang FROM post_comment WHERE approved = 1;"); break; case "photo_comment": $q = mysqli_query($con, "SELECT photo_comment.id AS id, post, text, dtime, username, lang FROM photo_comment WHERE approved = 1;"); break; case "sponsor": $q = mysqli_query($con, "SELECT id, name_es, name_en, name_eu, text_es, text_en, text_eu, image, address_es, address_en, address_eu, link, lat, lon FROM sponsor;"); break; case "settings": $q = mysqli_query($con, "SELECT name, value FROM settings"); break; //Other cases: default: //If the table is a public one and has not been listed above, all of its fields are public. if (in_array($table, ['activity_image', 'activity_itinerary', 'activity_tag', 'festival', 'festival_day', 'festival_event', 'festival_event_image', 'festival_offer', 'photo_album', 'place', 'people', 'post_image', 'post_tag'])){ $q = mysqli_query($con, "SELECT * FROM $table;"); } //If forbidden table else{ //'Forbidden' status code //TODO: I dont want execution stopping here http_response_code(403); return; } } //If no rows, return if (mysqli_num_rows($q) == 0){ return -1; } //Create result array $rows = array(); while($r = mysqli_fetch_assoc($q)) { $rows[] = $r; } return $rows; } /**************************************************** * gets the IP address of the client. * * * * @return: (String): Client IP address. * ****************************************************/ function get_user_ip(){ $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; if(filter_var($client, FILTER_VALIDATE_IP)){ $ip = $client; } elseif(filter_var($forward, FILTER_VALIDATE_IP)){ $ip = $forward; } else{ $ip = $remote; } return $ip; } /**************************************************** * Registers the request in the database. * * * * @params: * * con: (MySQL server connection) RO mode enough. * * client: (string): The client identifier. * * user: (string): A unique end user identifier. * * action: (string): Requested action. * * section: (string): Requested database section. * * version: (int): Version of the client db. * * new_version: (int): Returned version. * * foreground: (int): 1 for fg syncs, 0 for bg. * * format: (string): Requested format. * * error: (string): Error message to store. * ****************************************************/ function log_sync($con, $client, $user, $action, $section, $version, $new_version, $foreground, $format, $error){ $ip = get_user_ip(); $browser_data = get_browser(null, true); $os = $browser_data['platform']; $browser = $browser_data['browser']; $uagent = $browser_data['browser_name_pattern']; mysqli_query($con, "INSERT INTO sync (client, user, action, section, version_from, version_to, fg, format, error, ip, os, uagent) VALUES ('$client', '$user', '$action', '$section', $version, $new_version, $foreground, '$format', '$error', '$ip', '$os', '$uagent');"); error_log("INSERT INTO sync (client, user, action, section, version_from, version_to, fg, format, error, ip, os, uagent) VALUES ('$client', '$user', '$action', '$section', $version, $new_version, $foreground, '$format', '$error', '$ip', '$os', '$uagent');"); } //Connect to the database $con = startdb('rw'); //Get data from URL $client = mysqli_real_escape_string($con, $_GET[GET_CLIENT]); $user = mysqli_real_escape_string($con, $_GET[GET_USER]); $action = strtolower(mysqli_real_escape_string($con, $_GET[GET_ACTION])); $section = strtolower(mysqli_real_escape_string($con, $_GET[GET_SECTION])); $version = (int) mysqli_real_escape_string($con, $_GET[GET_VERSION]); $foregroud = (int) mysqli_real_escape_string($con, $_GET[GET_FOREGROUND]); $format = strtolower(mysqli_real_escape_string($con, $_GET[GET_FORMAT])); //Initialize some variables $error = ''; $new_version = -1; //Validate data if (strlen($client) < 1){ $client = ''; } if (strlen($user) < 1){ $user = ''; } if (strlen($action) < 1){ $action = DEF_ACTION; } if ($action != ACTION_SYNC && $action != ACTION_VERSION){ //Bad request http_response_code(400); $error = $error . ERR_ACTION . mysqli_real_escape_string($con, $_GET[GET_ACTION]); } if (strlen($section) > 0 && $section != SEC_ALL && $section != SEC_BLOG && $section != SEC_ACTIVITIES && $section != SEC_GALLERY && $section != SEC_LABLANCA ){ //Bad request http_response_code(400); $error = $error . ERR_SECTION . mysqli_real_escape_string($con, $_GET[GET_SECTION]); } if (strlen($section) == 0){ $section = SEC_ALL; } if (strlen($version) == 0){ $version = -1; } if (is_int($version) == false){ //Bad request http_response_code(400); $error = $error . ERR_VERSION . mysqli_real_escape_string($con, $_GET[GET_VERSION]); $version = -1; } if (strlen($foregroud) < 1){ $foreground = 1; } if ($foreground != 0 && $foregroud != 0){ //Bad request http_response_code(400); $error = $error . ERR_FOREGROUND . mysqli_real_escape_string($con, $_GET[GET_BACKGROUND]); } if (strlen($format) < 1){ $format = DEF_FORMAT; } if ($format != FOR_JSON){ //Bad request http_response_code(400); $error = $error . ERR_FORMAT . mysqli_real_escape_string($con, $_GET[GET_FORMAT]); } //If there has not been an error, procede if (strlen($error) == 0){ //If the client just needs to know the version number if ($action == ACTION_VERSION){ $new_version = get_version($con, $section); echo ($new_version); } //If the clients wants to actually perform a sync else{ //If the client version is up to date, send a no content status $new_version = get_version($con, $section); if ($version >= $new_version){ //No content http_response_code(204); } //If the client needs an update else{ $out = sync($con, $section); $out = str_replace('\"', '\u0022', $out); $out = str_replace(':""', ':null', $out); $out = "{\"sync\":$out}"; echo($out); } } } //Log the sync in the database log_sync($con, $client, $user, $action, $section, $version, $new_version, $foreground, $format, $error); ?>