4

I started to use Flurry Analytics and have found that it's analysing tools are insufficient and too slow. Simple funnel of 3 steps was processed for 3 days, while normally query with 3 left joins take 0,001 seconds on table with 100,000 rows.

Flurry allows to download raw event data in csv format on Event Logs page, so I decided to import all the events and analyze them at home.

Flurry allows to download only 100,000 records, and they advise just to download often to fit this limit. They had raw event download API but abandoned it for some reason. So the only way is to go to Event Logs page and download events data manually. But as you can imagine it is very annoying.

So I decided to get this data using curl in php. I've copied the GET HTTP request to download link with headers and got the data. But the whole magic is in session/cookies which I can just copy from existing session. So to make curl query succeed I have to:

  1. go to flurry site in browser and login
  2. go to Event Logs page, choose time frame parameters and click download
  3. copy request headers in sniffer
  4. paste them to my php code
  5. and from now on I can make this query in php until session cookies expire

I'm not sure but suppose cookies will expire on the next day, so the whole this effort is useless.

As I understand I should try to POST login with curl, and keeping this connection perform GET to download data. Yet I can not login even copying the whole POST login request body - it answers with the same login page although should 302 redirect to https://dev.flurry.com/fullPageTakeover.do?originalTarget=&isFirstPostLogin=true&defaultTarget=%2Fhome.do

It looks like flurry is somehow protected from such curl reading. Or maybe somebody succeed in it?

Here's the code:

    $cookie_file_path = "cookies.txt";
    $LOGINURL         = "https://dev.flurry.com/secure/login.do";
    $MY_EMAIL ="my email";
    $MY_PASS="password";
    $MY_GAME_ID="gameid";

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_HEADER,  0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt ($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
    curl_setopt ($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file_path);
    curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file_path);
    curl_setopt ($ch, CURLOPT_REFERER, $LOGINURL);


    curl_setopt($ch, CURLOPT_URL, $LOGINURL);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, "loginEmail=$MY_EMAIL&loginPassword=$MY_PASS&__checkbox_rememberMe=true&struts.token.name=struts.token&struts.token=7NB9NWLOYZ8SD8TWR8LGS63REVDI8SQS");

    $result = curl_exec($ch);


    $remotePageUrl = "https://dev.flurry.com/eventsLogCsv.do?projectID=$MY_GAME_ID&versionCut=versionsAll&intervalCut=7Days&stream=true&direction=1&offset=0";
    curl_setopt($ch, CURLOPT_POST, 0);
    curl_setopt($ch, CURLOPT_URL, $remotePageUrl);
    $result = curl_exec($ch);

    echo $result;

Also tried to pass cookies (like it does from browser), but nothing helped:

Cookie: _ga=GA1.2.100867533.1424333566; S0hZTkM0RFRXRjJNSlg2TVdXSEs_fit=1424333594147; fid=SG1162A8DEFC14B8428E7C2AFC71D3AEA00C1872F5; JSESSIONID=w34~mvbdvftm9x9dez9dg9b2pmhs; _map_zoomLevel=0;
_map_zoneId=0; __utmt=1; __utmt_~1=1; S0hZTkM0RFRXRjJNSlg2TVdXSEs_fs=eyJiYSI6MTQyNDMzNzkzMzU2OCwicGF1c2VUaW1lc3RhbXAiOjAsImJjIjotMSwiZXZlbnRDb3VudGVyIjowLCJwdXJjaGFzZUNvdW50ZXIiOjAsImVycm9yQ291bnRlciI6MCwidGltZWRFdmVudHMiOltdfQ==;
__utma=83277827.100867533.1424333566.1424333594.1424336847.2; __utmb=83277827.8.10.1424336847; __utmc=83277827; __utmz=83277827.1424333594.1.1.utmcsr=flurry.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utma=34058230.100867533.1424333566.1424333566.1424336847.2; __utmb=34058230.8.10.1424336847; __utmc=34058230; __utmz=34058230.1424333566.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _mkto_trk=id:802-TBR-126&token:_mch-flurry.com-1424333577360-64839; S0hZTkM0RFRXRjJNSlg2TVdXSEs_flp=1424338032448

Thanks to silkfire Flurry problem is solved!

Tertium
  • 6,049
  • 3
  • 30
  • 51
  • Are you having trouble with logging in? The link you posted still requires you to enter email and password. Show us your code of you performing this login request with cURL, please. – silkfire Feb 19 '15 at 10:09
  • @silkfire I've added one variant of test code. Theoretically everything should work, but flurry returns the same login page. – Tertium Feb 19 '15 at 10:24
  • I see nothing wrong with your cURL code. By the look of it, it should work. Unfortunately it's hard testing without having access to an account :( – silkfire Feb 19 '15 at 10:30
  • It takes several minutes to register: https://dev.flurry.com/secure/signup.do. Process involves email, so everyone should register himself. Flurry is free btw. – Tertium Feb 19 '15 at 10:44
  • If I'd register, where would I get a game ID from? – silkfire Feb 19 '15 at 10:47
  • It is an abstraction, it can be created after you log in. But for this you must log in. The only problem is that I can not login using curl. The rest things are trivial and done already. – Tertium Feb 19 '15 at 11:01
  • I just registered, is game ID same as Application key? 20 long string consisiting of capital letters? – silkfire Feb 19 '15 at 11:49
  • @silkfire no, it is a number like 535016. When you go to your game page you will see it in address string. – Tertium Feb 19 '15 at 12:07
  • Okay I managed to login. See my answer. – silkfire Feb 19 '15 at 12:25

1 Answers1

3

The struts.token is a CRSF token which is bound to your session and regenerated on each page load. In your code though, it's static. You need to fetch it after your first cURL request and then inject it into your POST array to be used for your second request.

Also the page you have to login to is /loginAction.do and not /login.do.

This is how I successfully logged in to Flurry:

$post = [
         'loginEmail'        => 'E-MAIL',
         'loginPassword'     => 'PASSWORD',
         'struts.token.name' => 'struts.token'
        ];

$ch = curl_init('https://dev.flurry.com/secure/login.do');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($ch, CURLOPT_COOKIEFILE, null);

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

libxml_use_internal_errors(true);

$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML(curl_exec($ch));

$xpath = new DOMXPath($dom);


$post['struts.token'] = $xpath->query('//input[@name="struts.token"]')->item(0)->getAttribute('value');

curl_setopt($ch, CURLOPT_URL, 'https://dev.flurry.com/secure/loginAction.do');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));

$data = curl_exec($ch);


echo $data;
silkfire
  • 24,585
  • 15
  • 82
  • 105
  • Thanks, brilliant! I've set CURLOPT_COOKIEFILE and CURLOPT_FILE also and GET to https://dev.flurry.com/eventsLogCsv.do was succeed! – Tertium Feb 19 '15 at 15:20
  • 1
    @Tertium Setting `CURLOPT_COOKIEFILE` to `null` is sufficient. It will allow your cURL handle to store cookies but they're only saved in memory and will not clutter up your project folder. – silkfire Feb 19 '15 at 15:24
  • Thanks, I just wanted to see what's there. – Tertium Feb 19 '15 at 15:28
  • Hi Silkfire & Tertium. I'm not very familiar with PHP and these types of scripts. I was wondering if one of you could provide a full solution based on your code to login to Flurry and fetch all log events. Currently I don't understand how the two scripts could do that. I would expect a for loop or something. Can you help if you have the time? Thank you. – Konrad Aug 17 '15 at 13:57
  • @silkfire I have integrated above code snippet but it generates fatal error "Fatal error: Call to a member function getAttribute() on a non-object" – Rubin Porwal Sep 02 '16 at 06:04
  • @RubinPorwal I think they've changed the way you login now. – silkfire Sep 02 '16 at 07:03
  • @silkfireYes they have modified authentication mechanism.Please refer http://stackoverflow.com/questions/39159305/perform-authentication-into-flurry-website-using-curl – Rubin Porwal Sep 02 '16 at 07:07
  • 1
    Who cares now, flurry data is bad, many events are ommited, even my own log handles them better. – Tertium May 06 '17 at 19:34