From 44cb03fb7683537e25bed43054bc27487be64201 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Mon, 21 Mar 2011 21:14:01 +0000 Subject: [PATCH 1/9] [drupal] handle $user->roles = NULL condition --- server/drupal/modules/logger/logger.module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/drupal/modules/logger/logger.module b/server/drupal/modules/logger/logger.module index 68b41c1..dac9d82 100644 --- a/server/drupal/modules/logger/logger.module +++ b/server/drupal/modules/logger/logger.module @@ -319,7 +319,7 @@ function _logger_dashboard($type, $function, $interval) { WHERE uid = %d AND type = '%s' AND function = '%s' ORDER BY created", $user->uid, $type, $function)); - if (in_array('pro', array_values($user->roles))) + if (is_array($user->roles) && in_array('pro', array_values($user->roles))) $result_me = db_query("SELECT meter, function FROM {logger_meters} WHERE uid = %d AND type = '%s' and chart = %d From de4e46531d82d9a71a9e009d2e304f2aae4dbc13 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Mon, 21 Mar 2011 21:14:51 +0000 Subject: [PATCH 2/9] [xmlrpc] comment out the authentication failure logging --- server/drupal/modules/logger/xmlrpc1.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/drupal/modules/logger/xmlrpc1.inc b/server/drupal/modules/logger/xmlrpc1.inc index 80296a9..4db9451 100644 --- a/server/drupal/modules/logger/xmlrpc1.inc +++ b/server/drupal/modules/logger/xmlrpc1.inc @@ -155,7 +155,7 @@ function _logger_authenticate_hmac_sha1($auth, $message) { return TRUE; } else { - watchdog_xmlrpc('logger.auth', 'HMAC-SHA1 authentication failed for device: %device', array('%device' => $auth['device']), WATCHDOG_ERROR); + // watchdog_xmlrpc('logger.auth', 'HMAC-SHA1 authentication failed for device: %device', array('%device' => $auth['device']), WATCHDOG_ERROR); return FALSE; } } From a80ea44ca302b35dfc6bd273b76c5322a295abf1 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Tue, 22 Mar 2011 20:23:55 +0000 Subject: [PATCH 3/9] [api] use /sensor endpoint for submitting measurement values --- server/api/flukso/src/flukso.app | 1 + server/api/flukso/src/flukso.erl | 3 +- server/api/flukso/src/flukso_sensor.erl | 105 ++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 server/api/flukso/src/flukso_sensor.erl diff --git a/server/api/flukso/src/flukso.app b/server/api/flukso/src/flukso.app index 0fe0969..166c852 100644 --- a/server/api/flukso/src/flukso.app +++ b/server/api/flukso/src/flukso.app @@ -6,6 +6,7 @@ flukso_app, flukso_sup, flukso_deps, + flukso_sensor, flukso_sensor_xyz ]}, {registered, []}, diff --git a/server/api/flukso/src/flukso.erl b/server/api/flukso/src/flukso.erl index 10ffaf6..7b1391c 100644 --- a/server/api/flukso/src/flukso.erl +++ b/server/api/flukso/src/flukso.erl @@ -16,7 +16,8 @@ ensure_started(App) -> end. mysql_prepare() -> - mysql:prepare(permissions, <<"SELECT permissions FROM logger_tokens WHERE meter = ? AND token = ?">>). + mysql:prepare(permissions, <<"SELECT permissions FROM logger_tokens WHERE meter = ? AND token = ?">>), + mysql:prepare(device_key, <<"SELECT sha FROM logger_devices WHERE device = ?">>). %% @spec start_link() -> {ok,Pid::pid()} %% @doc Starts the app for inclusion in a supervisor tree diff --git a/server/api/flukso/src/flukso_sensor.erl b/server/api/flukso/src/flukso_sensor.erl new file mode 100644 index 0000000..4039781 --- /dev/null +++ b/server/api/flukso/src/flukso_sensor.erl @@ -0,0 +1,105 @@ +%% @author icarus75 +%% @copyright 2009-2010 flukso.net +%% @doc Flukso webmachine_resource. + +-module(flukso_sensor). +-export([init/1, + allowed_methods/2, + malformed_request/2, + is_authorized/2, + process_post/2]). + +-include_lib("webmachine/include/webmachine.hrl"). + +-record(state, + {rrdSensor}). + +init([]) -> + {ok, undefined}. + +% debugging +%init(Config) -> +% {{trace, "/tmp"}, Config}. + +allowed_methods(ReqData, State) -> + {['POST'], ReqData, State}. + +malformed_request(ReqData, State) -> + {_Version, ValidVersion} = check_version(wrq:get_req_header("X-Version", ReqData), wrq:get_qs_value("version", ReqData)), +% TODO: check validity of X-Device and X-Digest headers + + {case {ValidVersion} of + {true} -> false; + _ -> true + end, + ReqData, State}. + +is_authorized(ReqData, State) -> + {data, Result} = mysql:execute(pool, device_key, [wrq:get_req_header("X-Device", ReqData)]), + [[Key]] = mysql:get_result_rows(Result), + Data = wrq:req_body(ReqData), + <> = crypto:sha_mac(Key, Data), + Digest = list_to_binary(io_lib:format("~40.16.0b", [X])), + + {case list_to_binary(wrq:get_req_header("X-Digest", ReqData)) of + Digest -> true; + _WrongDigest -> "access refused" + end, + ReqData, State}. + +% JSON: {"measurements":{"":[[,],...,[,]], +% ..., +% "":[[,],...,[,]]}} +% +% Mochijson2: {struct,[{<<"measurements">>, {struct, [{<<"">>, [[,],...,[,]]}, +% ..., +% {<<"">>, [[,],...,[,]]}]}}]} +% +process_post(ReqData, State) -> + {struct, JsonData} = mochijson2:decode(wrq:req_body(ReqData)), + {struct, Measurements} = proplists:get_value(<<"measurements">>, JsonData), + Ids = proplists:get_keys(Measurements), + RrdResponse = [update(RrdSensor, proplists:get_value(RrdSensor, Measurements)) || RrdSensor <- Ids], + + JsonResponse = mochijson2:encode({struct, [{<<"response">>, {struct, RrdResponse}}]}), + {true , wrq:set_resp_body(JsonResponse, ReqData), State}. + +update(RrdSensor, TimeSeries) -> + Path = "var/data/base/", + RrdData = [[integer_to_list(Time), ":", integer_to_list(Counter), " "] || [Time, Counter] <- TimeSeries], + +%debugging: io:format("~s~n", [[Path, [binary_to_list(RrdSensor)|".rrd"], " ", RrdData]]), + + case erlrrd:update([Path, [binary_to_list(RrdSensor)|".rrd"], " ", RrdData]) of + {ok, _RrdResponse} -> {RrdSensor, <<"ok">>}; + {error, RrdResponse} -> {RrdSensor, list_to_binary(RrdResponse)} + end. + + +%% checks +check_version(undefined, undefined) -> + {false, false}; +check_version(Version, undefined) -> + case Version of + "1.0" -> {Version, true}; + _ -> {false, false} + end; +check_version(undefined, Version) -> + check_version(Version, undefined); +check_version(_, _) -> + {false, false}. + +check_sensor(Sensor) -> + case re:run(Sensor, "[0-9a-f]+", []) of + {match, [{0,32}]} -> {Sensor, true}; + _ -> {false, false} + end. + +check_token(undefined, undefined) -> + {false, false}; +check_token(Token, undefined) -> + check_sensor(Token); +check_token(undefined, Token) -> + check_sensor(Token); +check_token(_, _) -> + {false, false}. From 90ffd3ffccda496275771ff482473d5cb6a0025e Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Tue, 22 Mar 2011 20:39:57 +0000 Subject: [PATCH 4/9] [api] add the /sensor endpoint to the dispatching rules --- server/api/flukso/priv/dispatch.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/server/api/flukso/priv/dispatch.conf b/server/api/flukso/priv/dispatch.conf index c56046c..4a73fc9 100644 --- a/server/api/flukso/priv/dispatch.conf +++ b/server/api/flukso/priv/dispatch.conf @@ -1 +1,2 @@ +{["sensor"], flukso_sensor, []}. {["sensor", sensor], flukso_sensor_xyz, []}. From 243d51222945f7a69fb1a19ef4807058bccc7007 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Wed, 23 Mar 2011 09:16:02 +0000 Subject: [PATCH 5/9] [api] add copyright header to webmachine files --- server/api/flukso/src/flukso.erl | 24 ++++++++++++++++----- server/api/flukso/src/flukso_app.erl | 21 ++++++++++++++---- server/api/flukso/src/flukso_deps.erl | 21 ++++++++++++++---- server/api/flukso/src/flukso_sensor.erl | 22 ++++++++++++++++--- server/api/flukso/src/flukso_sensor_xyz.erl | 22 ++++++++++++++++--- server/api/flukso/src/flukso_sup.erl | 23 +++++++++++++++----- 6 files changed, 109 insertions(+), 24 deletions(-) diff --git a/server/api/flukso/src/flukso.erl b/server/api/flukso/src/flukso.erl index 7b1391c..59a9cb3 100644 --- a/server/api/flukso/src/flukso.erl +++ b/server/api/flukso/src/flukso.erl @@ -1,10 +1,24 @@ -%% @author author -%% @copyright YYYY author. - -%% @doc TEMPLATE. +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% +%% @doc Flukso module spec -module(flukso). --author('author '). +-author('Bart Van Der Meerssche '). + -export([start/0, start_link/0, stop/0]). ensure_started(App) -> diff --git a/server/api/flukso/src/flukso_app.erl b/server/api/flukso/src/flukso_app.erl index ef7928d..37d59c4 100644 --- a/server/api/flukso/src/flukso_app.erl +++ b/server/api/flukso/src/flukso_app.erl @@ -1,10 +1,23 @@ -%% @author author -%% @copyright YYYY author. - +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% %% @doc Callbacks for the flukso application. -module(flukso_app). --author('author '). +-author('Bart Van Der Meerssche '). -behaviour(application). -export([start/2,stop/1]). diff --git a/server/api/flukso/src/flukso_deps.erl b/server/api/flukso/src/flukso_deps.erl index 7467e49..65ba78b 100644 --- a/server/api/flukso/src/flukso_deps.erl +++ b/server/api/flukso/src/flukso_deps.erl @@ -1,12 +1,25 @@ -%% @author author -%% @copyright YYYY author. - +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% %% @doc Ensure that the relatively-installed dependencies are on the code %% loading path, and locate resources relative %% to this application's path. -module(flukso_deps). --author('author '). +-author('Bart Van Der Meerssche '). -export([ensure/0, ensure/1]). -export([get_base_dir/0, get_base_dir/1]). diff --git a/server/api/flukso/src/flukso_sensor.erl b/server/api/flukso/src/flukso_sensor.erl index 4039781..05d029c 100644 --- a/server/api/flukso/src/flukso_sensor.erl +++ b/server/api/flukso/src/flukso_sensor.erl @@ -1,8 +1,24 @@ -%% @author icarus75 -%% @copyright 2009-2010 flukso.net -%% @doc Flukso webmachine_resource. +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% +%% @doc Flukso API: /sensor resource specification -module(flukso_sensor). +-author('Bart Van Der Meerssche '). + -export([init/1, allowed_methods/2, malformed_request/2, diff --git a/server/api/flukso/src/flukso_sensor_xyz.erl b/server/api/flukso/src/flukso_sensor_xyz.erl index 229760d..b764c62 100644 --- a/server/api/flukso/src/flukso_sensor_xyz.erl +++ b/server/api/flukso/src/flukso_sensor_xyz.erl @@ -1,8 +1,24 @@ -%% @author icarus75 -%% @copyright 2009-2010 flukso.net -%% @doc Flukso webmachine_resource. +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% +%% @doc Flukso API: /sensor/xyz resource specification -module(flukso_sensor_xyz). +-author('Bart Van Der Meerssche '). + -export([init/1, allowed_methods/2, malformed_request/2, diff --git a/server/api/flukso/src/flukso_sup.erl b/server/api/flukso/src/flukso_sup.erl index 3713ac6..025047b 100644 --- a/server/api/flukso/src/flukso_sup.erl +++ b/server/api/flukso/src/flukso_sup.erl @@ -1,10 +1,23 @@ -%% @author author -%% @copyright YYYY author. - -%% @doc Supervisor for the flukso application. +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% +%% @doc Supervisor for the flukso application. -module(flukso_sup). --author('author '). +-author('Bart Van Der Meerssche '). -behaviour(supervisor). From d64d41be3ab0bb5ce3cf607a436085d3fc5cde4d Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Wed, 23 Mar 2011 17:40:28 +0000 Subject: [PATCH 6/9] [api] move helper functions to a common flukso.hrl --- server/api/flukso/src/flukso.hrl | 144 +++++++++++++++++++ server/api/flukso/src/flukso_sensor.erl | 37 +---- server/api/flukso/src/flukso_sensor_xyz.erl | 146 +------------------- 3 files changed, 149 insertions(+), 178 deletions(-) diff --git a/server/api/flukso/src/flukso.hrl b/server/api/flukso/src/flukso.hrl index 8b13789..44edb2c 100644 --- a/server/api/flukso/src/flukso.hrl +++ b/server/api/flukso/src/flukso.hrl @@ -1 +1,145 @@ +%% @author Bart Van Der Meerssche +%% @copyright (C) 2009-2011 Bart Van Der Meerssche +%%% +%%% This program is free software: you can redistribute it and/or modify +%%% it under the terms of the GNU General Public License as published by +%%% the Free Software Foundation, either version 3 of the License, or +%%% (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%%% GNU General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program. If not, see . +%%% +%% @doc Common record definitions and helper functions for the Flukso API. +-record(state, + {rrdSensor, + rrdStart, + rrdEnd, + rrdResolution, + rrdFactor, + token, + jsonpCallback}). + +%% checks +check_version(undefined, undefined) -> + {false, false}; +check_version(Version, undefined) -> + case Version of + "1.0" -> {Version, true}; + _ -> {false, false} + end; +check_version(undefined, Version) -> + check_version(Version, undefined); +check_version(_, _) -> + {false, false}. + +check_sensor(Sensor) -> + case re:run(Sensor, "[0-9a-f]+", []) of + {match, [{0,32}]} -> {Sensor, true}; + _ -> {false, false} + end. + +check_time(undefined, undefined, _End, _Resolution) -> + {false, false, false, false}; +check_time(Interval, undefined, undefined, undefined) -> + case default_resolution(Interval) of + false -> {false, false, false, false}; + DefResolution -> check_time(Interval, undefined, undefined, DefResolution) + end; +check_time(Interval, undefined, undefined, Resolution) -> + Now = unix_time(), + case {time_to_seconds(Interval), time_to_seconds(Resolution)} of + {false, _} -> {false, false, false, false}; + {_, false} -> {false, false, false, false}; + {IntervalSec, ResolutionSec} -> + AlignedEnd = time_align(Now, ResolutionSec), + AlignedStart = AlignedEnd - IntervalSec, + {integer_to_list(AlignedStart), integer_to_list(AlignedEnd), integer_to_list(ResolutionSec), true} + end; +check_time(undefined, Start, undefined, Resolution) -> + check_time(undefined, Start, integer_to_list(unix_time()), Resolution); +check_time(undefined, Start, End, undefined) -> + check_time(undefined, Start, End, "minute"); +check_time(undefined, Start, End, Resolution) -> + case {re:run(Start, "[0-9]+", []), re:run(End, "[0-9]+", []), time_to_seconds(Resolution)} of + {_, _, false} -> {false, false, false, false}; + {{match, [{0,_}]}, {match, [{0,_}]}, ResolutionSec} -> + AlignedStart = time_align(list_to_integer(Start), ResolutionSec), + AlignedEnd = time_align(list_to_integer(End), ResolutionSec), + {integer_to_list(AlignedStart), integer_to_list(AlignedEnd), integer_to_list(ResolutionSec), true}; + _ -> {false, false, false, false} + end; +check_time(_, _, _, _) -> + {false, false, false, false}. + +check_unit(Unit) -> + Units = [{"watt", 3600}, + {"kwhperyear", 31536}, + {"eurperyear", 5676}, + {"audperyear", 5991}], + + case lists:keyfind(Unit, 1, Units) of + false -> {false, false}; + {_Unit, RrdFactor} -> {RrdFactor, true} + end. + +check_token(undefined, undefined) -> + {false, false}; +check_token(Token, undefined) -> + check_sensor(Token); +check_token(undefined, Token) -> + check_sensor(Token); +check_token(_, _) -> + {false, false}. + +check_jsonp_callback(undefined) -> + {undefined, true}; +check_jsonp_callback(JsonpCallback) -> + Length = string:len(JsonpCallback), + + case re:run(JsonpCallback, "[0-9a-zA-Z_]+", []) of + {match, [{0, Length}]} -> {JsonpCallback, true}; + _ -> {false, false} + end. + +%% helper functions +unix_time() -> + {Megaseconds, Seconds, _Microseconds} = erlang:now(), + Megaseconds*1000000 + Seconds. + +time_align(Time, Resolution) -> + (Time div Resolution) * Resolution. + +default_resolution(Interval) -> + DefResolutions = [{"15min", "minute"}, + {"hour", "minute"}, + {"day", "15min"}, + {"week", "day"}, + {"month", "day"}, + {"year", "week"}, + {"night", "day"}], + + case lists:keyfind(Interval, 1, DefResolutions) of + false -> false; + {_Interval, Defresolution} -> Defresolution + end. + +time_to_seconds(Time) -> + Times = [{"minute", 60}, + {"15min", 900}, + {"hour", 3600}, + {"day", 86400}, + {"week", 604800}, + {"month", 2419200}, + {"year", 31536000}, + {"night", 2419200}], + + case lists:keyfind(Time, 1, Times) of + false -> false; + {_Time, TimeSec} -> TimeSec + end. diff --git a/server/api/flukso/src/flukso_sensor.erl b/server/api/flukso/src/flukso_sensor.erl index 05d029c..a6f3e89 100644 --- a/server/api/flukso/src/flukso_sensor.erl +++ b/server/api/flukso/src/flukso_sensor.erl @@ -26,9 +26,7 @@ process_post/2]). -include_lib("webmachine/include/webmachine.hrl"). - --record(state, - {rrdSensor}). +-include("flukso.hrl"). init([]) -> {ok, undefined}. @@ -75,12 +73,12 @@ process_post(ReqData, State) -> {struct, JsonData} = mochijson2:decode(wrq:req_body(ReqData)), {struct, Measurements} = proplists:get_value(<<"measurements">>, JsonData), Ids = proplists:get_keys(Measurements), - RrdResponse = [update(RrdSensor, proplists:get_value(RrdSensor, Measurements)) || RrdSensor <- Ids], + RrdResponse = [update_rrd(RrdSensor, proplists:get_value(RrdSensor, Measurements)) || RrdSensor <- Ids], JsonResponse = mochijson2:encode({struct, [{<<"response">>, {struct, RrdResponse}}]}), {true , wrq:set_resp_body(JsonResponse, ReqData), State}. -update(RrdSensor, TimeSeries) -> +update_rrd(RrdSensor, TimeSeries) -> Path = "var/data/base/", RrdData = [[integer_to_list(Time), ":", integer_to_list(Counter), " "] || [Time, Counter] <- TimeSeries], @@ -90,32 +88,3 @@ update(RrdSensor, TimeSeries) -> {ok, _RrdResponse} -> {RrdSensor, <<"ok">>}; {error, RrdResponse} -> {RrdSensor, list_to_binary(RrdResponse)} end. - - -%% checks -check_version(undefined, undefined) -> - {false, false}; -check_version(Version, undefined) -> - case Version of - "1.0" -> {Version, true}; - _ -> {false, false} - end; -check_version(undefined, Version) -> - check_version(Version, undefined); -check_version(_, _) -> - {false, false}. - -check_sensor(Sensor) -> - case re:run(Sensor, "[0-9a-f]+", []) of - {match, [{0,32}]} -> {Sensor, true}; - _ -> {false, false} - end. - -check_token(undefined, undefined) -> - {false, false}; -check_token(Token, undefined) -> - check_sensor(Token); -check_token(undefined, Token) -> - check_sensor(Token); -check_token(_, _) -> - {false, false}. diff --git a/server/api/flukso/src/flukso_sensor_xyz.erl b/server/api/flukso/src/flukso_sensor_xyz.erl index b764c62..00ce506 100644 --- a/server/api/flukso/src/flukso_sensor_xyz.erl +++ b/server/api/flukso/src/flukso_sensor_xyz.erl @@ -28,15 +28,7 @@ process_post/2]). -include_lib("webmachine/include/webmachine.hrl"). - --record(state, - {rrdSensor, - rrdStart, - rrdEnd, - rrdResolution, - rrdFactor, - token, - jsonpCallback}). +-include("flukso.hrl"). init([]) -> {ok, undefined}. @@ -134,138 +126,4 @@ to_json(ReqData, #state{rrdSensor = RrdSensor, rrdStart = RrdStart, rrdEnd = Rrd end. process_post(ReqData, #state{rrdSensor = RrdSensor} = State) -> - Path = "var/data/base/", - - {struct, JsonData} = mochijson2:decode(wrq:req_body(ReqData)), - Measurements = proplists:get_value(<<"measurements">>, JsonData), - RrdData = [[integer_to_list(Time), ":", integer_to_list(Counter), " "] || [Time, Counter] <- Measurements], - -%debugging: io:format("~s~n", [[Path, [RrdSensor|".rrd"], " ", RrdData]]), - - case erlrrd:update([Path, [RrdSensor|".rrd"], " ", RrdData]) of - {ok, _RrdResponse} -> RrdResponse = "ok"; - {error, RrdResponse} -> true - end, - - JsonResponse = mochijson2:encode({struct, [{<<"response">>, list_to_binary(RrdResponse)}]}), - - {true , wrq:set_resp_body(JsonResponse, ReqData), State}. - -%% checks -check_version(undefined, undefined) -> - {false, false}; -check_version(Version, undefined) -> - case Version of - "1.0" -> {Version, true}; - _ -> {false, false} - end; -check_version(undefined, Version) -> - check_version(Version, undefined); -check_version(_, _) -> - {false, false}. - -check_sensor(Sensor) -> - case re:run(Sensor, "[0-9a-f]+", []) of - {match, [{0,32}]} -> {Sensor, true}; - _ -> {false, false} - end. - -check_time(undefined, undefined, _End, _Resolution) -> - {false, false, false, false}; -check_time(Interval, undefined, undefined, undefined) -> - case default_resolution(Interval) of - false -> {false, false, false, false}; - DefResolution -> check_time(Interval, undefined, undefined, DefResolution) - end; -check_time(Interval, undefined, undefined, Resolution) -> - Now = unix_time(), - case {time_to_seconds(Interval), time_to_seconds(Resolution)} of - {false, _} -> {false, false, false, false}; - {_, false} -> {false, false, false, false}; - {IntervalSec, ResolutionSec} -> - AlignedEnd = time_align(Now, ResolutionSec), - AlignedStart = AlignedEnd - IntervalSec, - {integer_to_list(AlignedStart), integer_to_list(AlignedEnd), integer_to_list(ResolutionSec), true} - end; -check_time(undefined, Start, undefined, Resolution) -> - check_time(undefined, Start, integer_to_list(unix_time()), Resolution); -check_time(undefined, Start, End, undefined) -> - check_time(undefined, Start, End, "minute"); -check_time(undefined, Start, End, Resolution) -> - case {re:run(Start, "[0-9]+", []), re:run(End, "[0-9]+", []), time_to_seconds(Resolution)} of - {_, _, false} -> {false, false, false, false}; - {{match, [{0,_}]}, {match, [{0,_}]}, ResolutionSec} -> - AlignedStart = time_align(list_to_integer(Start), ResolutionSec), - AlignedEnd = time_align(list_to_integer(End), ResolutionSec), - {integer_to_list(AlignedStart), integer_to_list(AlignedEnd), integer_to_list(ResolutionSec), true}; - _ -> {false, false, false, false} - end; -check_time(_, _, _, _) -> - {false, false, false, false}. - -check_unit(Unit) -> - Units = [{"watt", 3600}, - {"kwhperyear", 31536}, - {"eurperyear", 5676}, - {"audperyear", 5991}], - - case lists:keyfind(Unit, 1, Units) of - false -> {false, false}; - {_Unit, RrdFactor} -> {RrdFactor, true} - end. - -check_token(undefined, undefined) -> - {false, false}; -check_token(Token, undefined) -> - check_sensor(Token); -check_token(undefined, Token) -> - check_sensor(Token); -check_token(_, _) -> - {false, false}. - -check_jsonp_callback(undefined) -> - {undefined, true}; -check_jsonp_callback(JsonpCallback) -> - Length = string:len(JsonpCallback), - - case re:run(JsonpCallback, "[0-9a-zA-Z_]+", []) of - {match, [{0, Length}]} -> {JsonpCallback, true}; - _ -> {false, false} - end. - -%% helper functions -unix_time() -> - {Megaseconds, Seconds, _Microseconds} = erlang:now(), - Megaseconds*1000000 + Seconds. - -time_align(Time, Resolution) -> - (Time div Resolution) * Resolution. - -default_resolution(Interval) -> - DefResolutions = [{"15min", "minute"}, - {"hour", "minute"}, - {"day", "15min"}, - {"week", "day"}, - {"month", "day"}, - {"year", "week"}, - {"night", "day"}], - - case lists:keyfind(Interval, 1, DefResolutions) of - false -> false; - {_Interval, Defresolution} -> Defresolution - end. - -time_to_seconds(Time) -> - Times = [{"minute", 60}, - {"15min", 900}, - {"hour", 3600}, - {"day", 86400}, - {"week", 604800}, - {"month", 2419200}, - {"year", 31536000}, - {"night", 2419200}], - - case lists:keyfind(Time, 1, Times) of - false -> false; - {_Time, TimeSec} -> TimeSec - end. + {true , ReqData, State}. From 80073a5de58470b4f273be7652020abe6be1cb80 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Thu, 24 Mar 2011 07:13:27 +0000 Subject: [PATCH 7/9] [api] define a generic 32hex checking function --- server/api/flukso/src/flukso.hrl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/server/api/flukso/src/flukso.hrl b/server/api/flukso/src/flukso.hrl index 44edb2c..cfe2696 100644 --- a/server/api/flukso/src/flukso.hrl +++ b/server/api/flukso/src/flukso.hrl @@ -39,8 +39,11 @@ check_version(_, _) -> {false, false}. check_sensor(Sensor) -> - case re:run(Sensor, "[0-9a-f]+", []) of - {match, [{0,32}]} -> {Sensor, true}; + check_32hex(Sensor). + +check_32hex(String) -> + case re:run(String, "[0-9a-f]+", []) of + {match, [{0,32}]} -> {String, true}; _ -> {false, false} end. @@ -91,9 +94,9 @@ check_unit(Unit) -> check_token(undefined, undefined) -> {false, false}; check_token(Token, undefined) -> - check_sensor(Token); + check_32hex(Token); check_token(undefined, Token) -> - check_sensor(Token); + check_32hex(Token); check_token(_, _) -> {false, false}. From f8ba3937bbc5e7410165802e19416c1cd351a126 Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Thu, 24 Mar 2011 07:31:30 +0000 Subject: [PATCH 8/9] [api] add a device and digest check to /sensor --- server/api/flukso/src/flukso.hrl | 13 ++++++++----- server/api/flukso/src/flukso_sensor.erl | 9 +++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/server/api/flukso/src/flukso.hrl b/server/api/flukso/src/flukso.hrl index cfe2696..2aa6bd8 100644 --- a/server/api/flukso/src/flukso.hrl +++ b/server/api/flukso/src/flukso.hrl @@ -26,15 +26,18 @@ jsonpCallback}). %% checks -check_version(undefined, undefined) -> - {false, false}; -check_version(Version, undefined) -> +check_version(Version) -> case Version of "1.0" -> {Version, true}; _ -> {false, false} - end; + end. + +check_version(undefined, undefined) -> + {false, false}; +check_version(Version, undefined) -> + check_version(Version); check_version(undefined, Version) -> - check_version(Version, undefined); + check_version(Version); check_version(_, _) -> {false, false}. diff --git a/server/api/flukso/src/flukso_sensor.erl b/server/api/flukso/src/flukso_sensor.erl index a6f3e89..df72e4e 100644 --- a/server/api/flukso/src/flukso_sensor.erl +++ b/server/api/flukso/src/flukso_sensor.erl @@ -39,11 +39,12 @@ allowed_methods(ReqData, State) -> {['POST'], ReqData, State}. malformed_request(ReqData, State) -> - {_Version, ValidVersion} = check_version(wrq:get_req_header("X-Version", ReqData), wrq:get_qs_value("version", ReqData)), -% TODO: check validity of X-Device and X-Digest headers + {_Version, ValidVersion} = check_version(wrq:get_req_header("X-Version", ReqData)), + {_Device, ValidDevice} = check_32hex(wrq:get_req_header("X-Device", ReqData)), + {_Digest, ValidDigest} = check_32hex(wrq:get_req_header("X-Digest", ReqData)), - {case {ValidVersion} of - {true} -> false; + {case {ValidVersion, ValidDevice, ValidDigest} of + {true, true, true} -> false; _ -> true end, ReqData, State}. From 5ec3d9c92e5b7bdb57b8e947e1f3dbfb70844d6c Mon Sep 17 00:00:00 2001 From: Bart Van Der Meerssche Date: Thu, 24 Mar 2011 09:28:13 +0000 Subject: [PATCH 9/9] [api] define time constants --- server/api/flukso/src/flukso.hrl | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/server/api/flukso/src/flukso.hrl b/server/api/flukso/src/flukso.hrl index 2aa6bd8..98f94b1 100644 --- a/server/api/flukso/src/flukso.hrl +++ b/server/api/flukso/src/flukso.hrl @@ -16,6 +16,14 @@ %%% %% @doc Common record definitions and helper functions for the Flukso API. +-define(MINUTE, 60). +-define(QUARTER, 900). +-define(HOUR, 3600). +-define(DAY, 86400). +-define(WEEK, 604800). +-define(MONTH, 2419200). +-define(YEAR, 31536000). + -record(state, {rrdSensor, rrdStart, @@ -136,14 +144,14 @@ default_resolution(Interval) -> end. time_to_seconds(Time) -> - Times = [{"minute", 60}, - {"15min", 900}, - {"hour", 3600}, - {"day", 86400}, - {"week", 604800}, - {"month", 2419200}, - {"year", 31536000}, - {"night", 2419200}], + Times = [{"minute", ?MINUTE}, + {"15min", ?QUARTER}, + {"hour", ?HOUR}, + {"day", ?DAY}, + {"week", ?WEEK}, + {"month", ?MONTH}, + {"year", ?YEAR}, + {"night", ?MONTH}], case lists:keyfind(Time, 1, Times) of false -> false;