<commit_before>/*---------------------------------------------------------------------------
  Copyright 2013 Microsoft Corporation.
 
  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the file "license.txt" at the root of this distribution.
---------------------------------------------------------------------------*/

define(["../scripts/promise","../scripts/util"], function(Promise,Util) {

var onedriveOptions = {
  client_id     : "000000004C113E9D",
  redirect_uri  : "https://www.madoko.net/redirect/live", 
  scope         : ["wl.signin","wl.skydrive","wl.skydrive_update"],
  response_type : "token",
  secure_cookie : true,
};

var onedriveDomain = "https://apis.live.net/v5.0/";

/* Helpers */

function makeError( obj, premsg ) {
  var msg = "onedrive: " + (premsg ? premsg + ": " : "")
  if (obj && obj.error) {
    var err = obj.error.message || obj.error.toString();
    err = err.replace(/^WL\..*:\s*/,"").replace(/^.*?Detail:\s*/,"");
    if (Util.startsWith(err,"Cannot read property 'focus'")) err = "Cannot open dialog box. Enable pop-ups?";
    msg = msg + err; // + (obj.error.code ? " (" + obj.error.code + ")" : "");
  }
  else if (obj && typeof obj === "string") {
    msg = msg + obj;
  }
  else {
    msg = msg + "unknown error";
  }
  return msg;
}

function makePromise( call, premsg ) {
  return new Promise(call).then( 
    function(res) {
      return res;
    },
    function(err) {
      throw makeError(err,premsg);
    }
  );
}


/* Id's, paths, and sub-directories are quite a hassle :-( */

function onedriveGet( path ) {
  return Util.requestGET( onedriveDomain + path, { access_token: getAccessToken() } );
}

function infoFromId( fileId ) {
  return onedriveGet( fileId.toString() );
}

function pathFromId( id, path ) {
  if (path == null) path = "";
  if (id === null) return path;
  return infoFromId( id ).then( function(info) {
    if (info.parent_id === null || info.name==="SkyDrive" || info.name==="OneDrive") return path;
    return pathFromId( info.parent_id, (path ? Util.combine(info.name,path) : info.name));
  });
}

function rootInfo() {
  return onedriveGet( "me/skydrive" );
}

function _infoFromName( folderId, name ) {
  return onedriveGet( folderId + "/files").then( function(res) {
    var file = null;
    if (res.data) {
      for (var i = 0; i < res.data.length; i++) {
        var f = res.data[i];
        if (f.name == name) {
          file = f;
          break;
        }
      }
    }
    return file;
  });
}

function _infoFromSubDirs( info, parts ) {
  if (parts.length === 0) return Promise.resolved(info);
  var part = parts.shift();
  return _infoFromName( info.id, part ).then( function( subInfo ) {
    if (!subInfo) return null;
    return _infoFromSubDirs( subInfo, parts );
  });
}

function infoFromSubPath( folderId, path ) {
  return infoFromId( folderId ).then(function(info) {
    if (!path) return info;
    return _infoFromSubDirs( info, path.split("/") );    
  });
}

function infoFromPath( path ) {
  return rootInfo().then( function( info ) {
    return infoFromSubPath( info.id, path );
  });
}

function _ensureSubDirs( folderId, dirs, recurse ) {
  if (dirs.length === 0) return { id: folderId, created: false };
  var dir = dirs.shift();
  return _infoFromName( folderId, dir ).then( function(dirInfo) {
    if (dirInfo) return _ensureSubDirs( dirInfo.id, dirs );
    var url = onedriveDomain + folderId.toString();
    return Util.requestPOST( url, { access_token: getAccessToken() }, { 
      name: dir, 
      description: "" 
    }).then( function(newInfo) {
      if (dirs.length===0) return { id: newInfo.id, created: true }; // remember we created it
      return _ensureSubDirs( newInfo.id, dirs );
    }, function(err) {
      if (!recurse && err && Util.contains(err.message,"(resource_already_exists)")) {
        // multiple requests can result in this error, try once more
        dirs.unshift(dir);
        return _ensureSubDirs( folderId, dirs, true );
      }
      else {
        throw err; // re-throw
      }    
    });
  });
}

function ensureSubPath( folderId, path ) {
  if (!path) return Promise.resolved( { id: folderId, created: false } );
  return _ensureSubDirs( folderId, path.split("/"));
}

function ensurePath( path ) {
  return rootInfo().then( function(info) {
    return ensureSubPath( info.id, path );
  });
}


/* Login */

var _access_token = null;
function getAccessToken() {
  return _access_token;
}

function login(dontForce) {
  if (getAccessToken()) return Promise.resolved();
  if (dontForce) return Promise.rejected( new Error("onedrive: not logged in") );
  try {
    WL.init(onedriveOptions); // ignore the promise.. or we trigger popup blockers
    if (console && console.log) {
      // fix these or the live.js script will call the wrong entries
      if (!console.error) console.error = console.log;
      if (!console.warn) console.warn = console.log;
    }
  }
  catch(exn) {}
  return makePromise(WL.login()).then( function() {
    var session = WL.getSession();
    if (session) _access_token = session.access_token;
    WL.Event.subscribe("auth.sessionChange", function(ev) {
      var xsession = WL.getSession();
      if (xsession) _access_token = xsession.access_token;
    });
    WL.Event.subscribe("auth.logout", function(ev) {
      _access_token = null;
    });
    return;
  });
}

function logout() {
  WL.logout();
}

/* Open a file */

function chooseFile() {
  return makePromise( WL.fileDialog( {
    mode: "open",
    select: "single",
  })).then( function(res) {
    if (!(res.data && res.data.files && res.data.files.length==1)) {
      throw new Error("onedrive: no file selected");
    }
    return res.data.files[0];
  }).then( function(file) {
    return infoFromId( file.id );
  });
}     

function openFile() {
  return login().then( function() {
    return chooseFile();
  }).then( function(info) {
    return pathFromId( info.parent_id ).then( function(path) {
      return { remote: new Onedrive(info.parent_id, path), docName: Util.basename(info.name) };
    });
  });
}

function openFolder() {
  return makePromise( WL.fileDialog( {
    mode: "save",
    select: "single",
  })).then( function(res) {
    if (!(res.data && res.data.folders && res.data.folders.length==1)) {
      return Promise.rejected(onedriveError("no save folder selected"));
    }
    return res.data.folders[0].id;
  }).then( function(folderId) {
    return pathFromId( folderId ).then( function(folder) {
      return new Onedrive(folderId, folder);
    });
  });
}     

/* Write a file */

function _writeFileAt( folderId, name, content ) {
  var url = onedriveDomain + folderId.toString() + "/files/" + name;                  
  return Util.requestPUT( {url:url, contentType:";" }, { access_token: getAccessToken() }, content );
}

function writeFile( folderId, path, content ) {
  return ensureSubPath( folderId, Util.dirname(path) ).then( function(info) {
    return _writeFileAt( info.id, Util.basename(path), content );
  }).then( function(resp) {
    return infoFromId( resp.id );
  });
}


/* Onedrive interface */

function unpersist( obj ) {
  return new Onedrive(obj.folderId, obj.folder || "");
}

function type() {
  return "Onedrive";
}

function createAt( folder ) {
  return login().then( function() {
    return ensurePath(folder);
  }).then( function(info) {
    return new Onedrive(info.id,folder);
  });
}

var Onedrive = (function() {

  function Onedrive( folderId, folder ) {
    var self = this;
    self.folderId = folderId;<commit_msg>Updated onedrive authorization to avoid popup blockers<commit_after>/*---------------------------------------------------------------------------
  Copyright 2013 Microsoft Corporation.
 
  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the file "license.txt" at the root of this distribution.
---------------------------------------------------------------------------*/

define(["../scripts/promise","../scripts/util"], function(Promise,Util) {

var onedriveOptions = {
  client_id     : "000000004C113E9D",
  redirect_uri  : "https://www.madoko.net/redirect/live", 
  scope         : ["wl.signin","wl.skydrive","wl.skydrive_update"],
  response_type : "token",
  secure_cookie : true,
};

var onedriveDomain = "https://apis.live.net/v5.0/";

/* Helpers */

function makeError( obj, premsg ) {
  var msg = "onedrive: " + (premsg ? premsg + ": " : "")
  if (obj && obj.error) {
    var err = obj.error.message || obj.error.toString();
    err = err.replace(/^WL\..*:\s*/,"").replace(/^.*?Detail:\s*/,"");
    if (Util.startsWith(err,"Cannot read property 'focus'")) err = "Cannot open dialog box. Enable pop-ups?";
    msg = msg + err; // + (obj.error.code ? " (" + obj.error.code + ")" : "");
  }
  else if (obj && typeof obj === "string") {
    msg = msg + obj;
  }
  else {
    msg = msg + "unknown error";
  }
  return msg;
}

function makePromise( call, premsg ) {
  return new Promise(call).then( 
    function(res) {
      return res;
    },
    function(err) {
      throw makeError(err,premsg);
    }
  );
}


/* ----------------------------------------------
   Id's, paths, and sub-directories are quite a hassle :-(
---------------------------------------------- */


function onedriveGet( path ) {
  return Util.requestGET( onedriveDomain + path, { access_token: getAccessToken() } );
}

function infoFromId( fileId ) {
  return onedriveGet( fileId.toString() );
}

function pathFromId( id, path ) {
  if (path == null) path = "";
  if (id === null) return path;
  return infoFromId( id ).then( function(info) {
    if (info.parent_id === null || info.name==="SkyDrive" || info.name==="OneDrive") return path;
    return pathFromId( info.parent_id, (path ? Util.combine(info.name,path) : info.name));
  });
}

function rootInfo() {
  return onedriveGet( "me/skydrive" );
}

function _infoFromName( folderId, name ) {
  return onedriveGet( folderId + "/files").then( function(res) {
    var file = null;
    if (res.data) {
      for (var i = 0; i < res.data.length; i++) {
        var f = res.data[i];
        if (f.name == name) {
          file = f;
          break;
        }
      }
    }
    return file;
  });
}

function _infoFromSubDirs( info, parts ) {
  if (parts.length === 0) return Promise.resolved(info);
  var part = parts.shift();
  return _infoFromName( info.id, part ).then( function( subInfo ) {
    if (!subInfo) return null;
    return _infoFromSubDirs( subInfo, parts );
  });
}

function infoFromSubPath( folderId, path ) {
  return infoFromId( folderId ).then(function(info) {
    if (!path) return info;
    return _infoFromSubDirs( info, path.split("/") );    
  });
}

function infoFromPath( path ) {
  return rootInfo().then( function( info ) {
    return infoFromSubPath( info.id, path );
  });
}

function _ensureSubDirs( folderId, dirs, recurse ) {
  if (dirs.length === 0) return { id: folderId, created: false };
  var dir = dirs.shift();
  return _infoFromName( folderId, dir ).then( function(dirInfo) {
    if (dirInfo) return _ensureSubDirs( dirInfo.id, dirs );
    var url = onedriveDomain + folderId.toString();
    return Util.requestPOST( url, { access_token: getAccessToken() }, { 
      name: dir, 
      description: "" 
    }).then( function(newInfo) {
      if (dirs.length===0) return { id: newInfo.id, created: true }; // remember we created it
      return _ensureSubDirs( newInfo.id, dirs );
    }, function(err) {
      if (!recurse && err && Util.contains(err.message,"(resource_already_exists)")) {
        // multiple requests can result in this error, try once more
        dirs.unshift(dir);
        return _ensureSubDirs( folderId, dirs, true );
      }
      else {
        throw err; // re-throw
      }    
    });
  });
}

function ensureSubPath( folderId, path ) {
  if (!path) return Promise.resolved( { id: folderId, created: false } );
  return _ensureSubDirs( folderId, path.split("/"));
}

function ensurePath( path ) {
  return rootInfo().then( function(info) {
    return ensureSubPath( info.id, path );
  });
}

/* Write a file */

function _writeFileAt( folderId, name, content ) {
  var url = onedriveDomain + folderId.toString() + "/files/" + name;                  
  return Util.requestPUT( {url:url, contentType:";" }, { access_token: getAccessToken() }, content );
}

function writeFile( folderId, path, content ) {
  return ensureSubPath( folderId, Util.dirname(path) ).then( function(info) {
    return _writeFileAt( info.id, Util.basename(path), content );
  }).then( function(resp) {
    return infoFromId( resp.id );
  });
}


/* ----------------------------------------------
  login
---------------------------------------------- */

var _access_token = null;
function getAccessToken() {
  return _access_token;
}

function init() {
  if (getAccessToken()) return true;
  try {
    WL.init(onedriveOptions); // ignore the promise.. or we trigger popup blockers
    if (console && console.log) {
      // fix these or the live.js script will call the wrong entries
      if (!console.error) console.error = console.log;
      if (!console.warn) console.warn = console.log;
    }
    WL.Event.subscribe("auth.sessionChange", function(ev) {
      var xsession = WL.getSession();
      if (xsession) _access_token = xsession.access_token;
    });
    WL.Event.subscribe("auth.logout", function(ev) {
      _access_token = null;
    });
    return true;
  }
  catch(exn) {
    return false;
  }
}

function login(dontForce) {
  if (getAccessToken()) return Promise.resolved();
  if (dontForce) return Promise.rejected( new Error("onedrive: not logged in") );
  init();
  return makePromise(WL.login()).then( function() {
    var session = WL.getSession();
    if (session) _access_token = session.access_token;
    return;
  });
}

function logout() {
  WL.logout();
}


function chooseFile() {
  return makePromise( WL.fileDialog( {
    mode: "open",
    select: "single",
  })).then( function(res) {
    if (!(res.data && res.data.files && res.data.files.length==1)) {
      throw new Error("onedrive: no file selected");
    }
    return res.data.files[0];
  }).then( function(file) {
    return infoFromId( file.id );
  });
}     

/* ----------------------------------------------
  Main entry points
---------------------------------------------- */

function openFile() {
  init();  // chooseFile will also login if necessary
  return chooseFile().then( function(info) {
    return pathFromId( info.parent_id ).then( function(path) {
      return { remote: new Onedrive(info.parent_id, path), docName: Util.basename(info.name) };
    });
  });
}

function createAt( folder ) {
  return login().then( function() {
    return ensurePath(folder);
  }).then( function(info) {
    return new Onedrive(info.id,folder);
  });
}


function openFolder() {
  return makePromise( WL.fileDialog( {
    mode: "save",
    select: "single",
  })).then( function(res) {
    if (!(res.data && res.data.folders && res.data.folders.length==1)) {
      return Promise.rejected(onedriveError("no save folder selected"));
    }
    return res.data.folders[0].id;
  }).then( function(folderId) {
    return pathFromId( folderId ).then( function(folder) {
      return new Onedrive(folderId, folder);
    });
  });
}     


/* ----------------------------------------------
  Remote interface
---------------------------------------------- */

function unpersist( obj ) {
  return new Onedrive(obj.folderId, obj.folder || "");
}

function type() {
  return "Onedrive";
}

var Onedrive = (function() {

  function Onedrive( folderId, folder ) {
    var self = this;
    self.folderId = folderId;
{'fraction_non_alphanumeric': 0.19233445069888053, 'fraction_numerical': 0.0036683321738030486, 'mean_word_length': 2.644157640009219, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2962287', 'n_tokens_mistral': 5061, 'n_tokens_neox': 4969, 'n_words': 1273}