diff --git a/about.php b/about.php index 50b19a4a..86fa2af8 100644 --- a/about.php +++ b/about.php @@ -248,6 +248,16 @@

Your password is stored according to best practices, with a salted hash stored with 10,000 of PBKDF2. Your data is physically located on servers at UC Berkeley.

+

GDPR Compliance

+

+ All personal information we collect about you, other than transient information like your last login IP address and time, is available from your personal profile page. If it's not visible on that page, we don't have that information about you. +

+

+ Your basic contact data is visible to others to the extent configured on your profile page, and is searchable when adding collaborators or filtering projects. +

+

+ Any new session irretrievably overwrites old transient data about you, and such transient data only reflects your current session (not historical). You may delete your account permanantly and irretrievably by visiting your dashboard, going to account settings, expanding the "more" button, and selecting "Remove Account". +

Disclaimer

Use of Data

@@ -272,7 +282,7 @@

amphibiandisease.org has no regulatory authority, and submitting data to it does not constitute an official - pathogen-reporting record. + pathogen-reporting record.

diff --git a/admin-api.php b/admin-api.php index 5ed66fba..7b55ee6e 100644 --- a/admin-api.php +++ b/admin-api.php @@ -1208,7 +1208,7 @@ function mintBcid($projectLink, $datasetRelativeUri = null, $datasetTitle, $addT ))."\r\n", )); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsAuthUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsAuthUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 001 (No Response)")); } @@ -1245,7 +1245,7 @@ function mintBcid($projectLink, $datasetRelativeUri = null, $datasetTitle, $addT $params['http']['header'] = $headers; $params['http']['content'] = http_build_query($fimsMintData); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsMintUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsMintUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 002 (No Response)")); } @@ -1359,7 +1359,7 @@ function associateBcidsWithExpeditions($projectLink, $fimsAuthCookiesAsString = ))."\r\n", )); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsAuthUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsAuthUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 003 (No Response)")); } @@ -1402,7 +1402,7 @@ function associateBcidsWithExpeditions($projectLink, $fimsAuthCookiesAsString = $tempAssociationData['bcid'] = $bcid; $params['http']['content'] = http_build_query($tempAssociationData); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsAssociateUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsAssociateUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 004 (No Response)")); } @@ -1515,7 +1515,7 @@ function mintExpedition($projectLink, $projectTitle, $publicProject = false, $as 'header' => implode("\r\n", $fimsDefaultHeaders)."\r\n", )); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsAuthUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsAuthUrl, false, $ctx); if ($rawResponse === false) { error_log("POST login failed!! Sent post:\n\tTarget URL:\t".$fimsAuthUrl."\n\tParameters:\t".print_r($params, true)."\n\tFull Context:\t".print_r($ctx, True)."\n\nResponse: ".print_r($rawResponse, true)); throw(new Exception("Fatal FIMS communication error 005 (No Response)")); @@ -1550,7 +1550,7 @@ function mintExpedition($projectLink, $projectTitle, $publicProject = false, $as $params['http']['header'] = $header; $params['http']['content'] = http_build_query($fimsMintData); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsMintUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsMintUrl, false, $ctx); $resp = null; if ($rawResponse === false) { $errorOut = true; @@ -1583,7 +1583,7 @@ function mintExpedition($projectLink, $projectTitle, $publicProject = false, $as 'header' => implode("\r\n", $fimsDefaultHeaders)."\r\n", )); $ctx = stream_context_create($params); - $rawReauthResponse = file_get_contents($fimsAuthUrl, false, $ctx); + $rawReauthResponse = file_get_contents_curl($fimsAuthUrl, false, $ctx); if ($rawReauthResponse === false) { error_log("POST reauth failed!! Sent post:\n\tTarget URL:\t".$fimsAuthUrl."\n\tParameters:\t".print_r($params, true)."\n\tFull Context:\t".print_r($ctx, True)."\n\nResponse: ".print_r($rawReauthResponse, true)); throw(new Exception("Fatal FIMS communication error 009 (No Response)")); @@ -1667,7 +1667,7 @@ function mintExpedition($projectLink, $projectTitle, $publicProject = false, $as $params["http"]["method"] = "GET"; unset($params["http"]["content"]); $ctx = stream_context_create($params); - $rawResponse2 = file_get_contents($target, false, $ctx); + $rawResponse2 = file_get_contents_curl($target, false, $ctx); $resp = json_decode($rawResponse2, true); $rawResponse = array( "original_response" => $rawResponse, @@ -1748,11 +1748,11 @@ function validateDataset($dataPath, $projectLink, $fimsAuthCookiesAsString = nul )); $params['http']['header'] .= "Cookie: ".$cookiesString."\r\n"; $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsStatusUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsStatusUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 007 (No Response)")); } - $rawResponse2 = file_get_contents($fimsContinueUrl, false, $ctx); + $rawResponse2 = file_get_contents_curl($fimsContinueUrl, false, $ctx); $resp = json_decode($rawResponse, true); $resp2 = json_decode($rawResponse2, true); @@ -1829,7 +1829,7 @@ function validateDataset($dataPath, $projectLink, $fimsAuthCookiesAsString = nul ))."\r\n", )); $ctx = stream_context_create($params); - $rawResponse = file_get_contents($fimsAuthUrl, false, $ctx); + $rawResponse = file_get_contents_curl($fimsAuthUrl, false, $ctx); if ($rawResponse === false) { throw(new Exception("Fatal FIMS communication error 008 (No Response)")); } diff --git a/admin/core/core.php b/admin/core/core.php index daf47034..e3978716 100644 --- a/admin/core/core.php +++ b/admin/core/core.php @@ -1,5 +1,24 @@ siteKey; @@ -280,7 +280,7 @@ public function getUser($user_id = null) * @param string|array $user_id Either a column/value pair or an ID for the default column * @return array of the user result column ***/ - + if (empty($this->user) || !empty($user_id)) { $this->setUser($user_id); } elseif (empty($this->user)) { @@ -523,7 +523,7 @@ public function canSMS($strict = true, $throw = true) # If we're strict, the user only can SMS when the phone number is verified. # Otherwise, we just return the status of the phone number itself. $verified = $strict ? $userdata['phone_verified'] == true : self::isValidPhone($this->getPhone()); - + return $verified; } @@ -539,7 +539,7 @@ private static function cleanPhone($number) if (substr($number, 0, 1) == '1') { $number = substr($number, 1); } - + return $number; } @@ -695,7 +695,7 @@ public function makeTOTP($provider = null) /* $iphone32 = str_replace("=","",$secret_part[1]); */ /* $iphone_uri = $secret_part[0]."secret=".$iphone32; #still no good */ $retarr = self::generateQR($iphone_uri); - + # Let's get a human-readable secret $human_secret0 = str_replace('=', '', $secret); $i = 0; @@ -744,14 +744,14 @@ public function saveTOTP($code) if ($r === false) { $e = mysqli_error($l); mysqli_query($l, 'ROLLBACK'); - + return array('status' => false,'error' => $e,'human_error' => 'Could not save secret','username' => $this->username); } $r = mysqli_query($l, $query2); if ($r === false) { $e = mysqli_error($l); mysqli_query($l, 'ROLLBACK'); - + return array('status' => false,'error' => $e,'human_error' => 'Could not create backup code','username' => $this->username); } mysqli_query($l, 'COMMIT'); @@ -819,7 +819,7 @@ public function removeTOTP($username, $password, $code) if ($r === false) { return array('status' => false,'error' => mysqli_error($l),'human_error' => 'Server error verifying removal. Please try again.'); } - + return array('status' => true,'query' => $query,'username' => $this->getUsername()); } @@ -838,7 +838,7 @@ public function sendTOTPText() $totp->setDigest($this->getDigest()); $message = 'Your authentication code for '.$this->getSiteName().' is: '.$totp->now().' . It is valid for 30 seconds.'; $this->textUser($message); - + return true; } catch (Exception $e) { return false; @@ -894,7 +894,7 @@ public static function generateQR($uri, $data_path = null, $identifier_path = nu if (function_exists('ImageCreate')) { QRcode::png($uri, $filename, QR_ECLEVEL_H, 8, 1); } - $raw = base64_encode(file_get_contents($filename)); + $raw = base64_encode(file_get_contents_curl($filename)); $raw = 'data:image/png;base64,'.$raw; if (!$persistent) { unlink($filename); @@ -902,7 +902,7 @@ public static function generateQR($uri, $data_path = null, $identifier_path = nu # As a final option, get a URL fallback # https://developers.google.com/chart/infographics/docs/qr_codes?csw=1 $url = 'https://chart.googleapis.com/chart?cht=qr&chs=500x500&chld=H&chl='.$uri; - + return array('status' => true,'uri' => $uri,'svg' => $svg,'raw' => $raw,'url' => $url); } catch (Exception $e) { return array('status' => false,'human_error' => 'Unable to generate QR code','error' => $e->getMessage(),'uri' => $uri,'identifier' => $identifier,'persistent' => $persistent); @@ -1370,7 +1370,7 @@ public function sendEmailVerification($alternate = false) { } - public function mailSuperusers($subject, $body) + public function mailSuperusers($subject, $body) { /*** * Send an email to site superusers @@ -1402,8 +1402,8 @@ public function mailSuperusers($subject, $body) "error" => $error, ); } - - public function isVerified($alternate = false) + + public function isVerified($alternate = false) { $key = $alternate ? "alternate_email_verified" : "email_verified"; $colCheck = array( @@ -1690,7 +1690,7 @@ public function setImageAsUserPicture($image, $path = null) { $image = str_replace($path, "", $image); } $sourceImage = $path . $image; - $imageData = file_get_contents($sourceImage); + $imageData = file_get_contents_curl($sourceImage); $iParts = explode(".", $image); $extension = array_pop($iParts); $imgUri = $path.$this->getHardlink().'.'.$extension; diff --git a/api.php b/api.php index 12790802..fa4025ef 100644 --- a/api.php +++ b/api.php @@ -367,6 +367,7 @@ function doCartoSqlApiPush($get) "insert" => "EDIT", "insertinto" => "EDIT", "update" => "EDIT", + "ifexists(\nselect1\nfrominformation_schema.tables\nwhere\n)drop" => "EDIT", ); $unrestrictedActions = array( "create" => true, @@ -399,6 +400,7 @@ function doCartoSqlApiPush($get) $checkedTablePermissions[] = $cartoTable; $cartoTableJson = str_replace('_', '_', $cartoTable); $accessListLookupQuery = 'SELECT `project_id`, `author`, `access_data`, `public` FROM `'.$db->getTable()."` WHERE `carto_id` LIKE '%".$cartoTableJson."%' OR `carto_id` LIKE '%".$cartoTable."%'"; + //#' # Syntax highlight helper $l = $db->openDB(); $r = mysqli_query($l, $accessListLookupQuery); $row = mysqli_fetch_assoc($r); @@ -552,7 +554,7 @@ function doCartoSqlApiPush($get) ), ); $context = stream_context_create($opts); - $response = file_get_contents($cartoFullUrl, false, $context); + $response = file_get_contents_curl($cartoFullUrl, false, $context); $responses[] = $response; $decoded = json_decode($response, true); $decoded["query"] = $statement; @@ -575,7 +577,7 @@ function doCartoSqlApiPush($get) ), ); $context = stream_context_create($opts); - $response = file_get_contents($cartoFullUrl, false, $context); + $response = file_get_contents_curl($cartoFullUrl, false, $context); $responses[] = $response; $decoded = json_decode($response, true); $decoded["query"] = $sqlQuery; @@ -659,7 +661,7 @@ function doAWebValidate($get) # How old is our copy? if (filemtime($localAWebTarget) + $dayOffset < time()) { # Fetch a new copy - $aWebList = file_get_contents($amphibiaWebListTarget); + $aWebList = file_get_contents_curl($amphibiaWebListTarget); if (strlen($aWebList) > 0) { $h = fopen($localAWebTarget, 'w+'); $bytes = fwrite($h, $aWebList); @@ -674,7 +676,7 @@ function doAWebValidate($get) } $response['aweb_list_age'] = time() - filemtime($localAWebTarget); $response['aweb_list_max_age'] = $dayOffset; - //$aWebList = file_get_contents($localAWebTarget); + //$aWebList = file_get_contents_curl($localAWebTarget); $aWebListArray = array_map('tsvHelper', file($localAWebTarget)); /* * For a given row, we have this numeric key to real id mapping: diff --git a/coffee/admin-editor.coffee b/coffee/admin-editor.coffee index 100ffe32..a80c9d8e 100644 --- a/coffee/admin-editor.coffee +++ b/coffee/admin-editor.coffee @@ -1031,7 +1031,10 @@ showAddUserDialog = (refAccessList) -> for uid in toAddUids user = toAddEmails[i] console.info "Adding", user - userName = $(user).text() + try + userName = user.text() + catch + userName = $(user).text() ++i html = """ @@ -2107,6 +2110,9 @@ revalidateAndUpdateData = (newFilePath = false, skipCallback = false, testOnly = # Finalizing callback finalize = -> # Save it + # Update the file downloader link + $("#download-project-file").attr("data-href", correctedPath) + console.info "Raw data download repointed to", correctedPath _adp.skipRead = true _adp.dataBu = _adp.projectData if skipSave is true diff --git a/core/core.php b/core/core.php index 7fcb8549..86d9aaf8 100644 --- a/core/core.php +++ b/core/core.php @@ -4,6 +4,26 @@ parse_str($_SERVER['QUERY_STRING'], $_REQUEST); } +if (!function_exists('file_get_contents_curl')) { + # cURL replacement for file_get_contents + # https://gist.github.com/tigerhawkvok/794a725436ae0b29db3ab17812828818 + function file_get_contents_curl($url) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); + + # Actual fetch + $data = curl_exec($ch); + curl_close($ch); + + return $data; + } +} + + if (!function_exists('microtime_float')) { function microtime_float() { @@ -290,7 +310,7 @@ function get_redirect_url($url) { /** * get_redirect_url() * Gets the address that the provided URL redirects to, - * or FALSE if there's no redirect. + * or FALSE if there's no redirect. * * @param string $url * @return string diff --git a/helpers/js-dragdrop/core/core.php b/helpers/js-dragdrop/core/core.php index 36ac2bfb..bdc20b8d 100644 --- a/helpers/js-dragdrop/core/core.php +++ b/helpers/js-dragdrop/core/core.php @@ -8,6 +8,26 @@ * @license MIT / GPL-3 dual-license ***/ +if (!function_exists('file_get_contents_curl')) { + # cURL replacement for file_get_contents + # https://gist.github.com/tigerhawkvok/794a725436ae0b29db3ab17812828818 + function file_get_contents_curl($url) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); + + # Actual fetch + $data = curl_exec($ch); + curl_close($ch); + + return $data; + } +} + + if (!function_exists('microtime_float')) { function microtime_float() { diff --git a/js/admin.js b/js/admin.js index a28bea13..70a0f73c 100644 --- a/js/admin.js +++ b/js/admin.js @@ -3449,7 +3449,7 @@ showAddUserDialog = function(refAccessList) { args = "perform=editaccess&project=" + window.projectParams.pid + "&deltas=" + uidArgs; console.log("Would push args to", adminParams.apiTarget + "?" + args); return _adp.currentAsyncJqxhr = $.post(adminParams.apiTarget, args, "json").done(function(result) { - var error, html, i, icon, len1, m, ref1, ref2, tense, uid, userName, userObj; + var error, error1, html, i, icon, len1, m, ref1, ref2, tense, uid, userName, userObj; console.log("Server permissions said", result); if (result.status !== true) { error = (ref1 = (ref2 = result.human_error) != null ? ref2 : result.error) != null ? ref1 : "We couldn't update user permissions"; @@ -3466,7 +3466,11 @@ showAddUserDialog = function(refAccessList) { uid = toAddUids[m]; user = toAddEmails[i]; console.info("Adding", user); - userName = $(user).text(); + try { + userName = user.text(); + } catch (error1) { + userName = $(user).text(); + } ++i; html = "\n " + userName + "\n " + icon + "\n"; $("#permissions-table").append(html); @@ -4534,6 +4538,8 @@ revalidateAndUpdateData = function(newFilePath, skipCallback, testOnly, skipSave recalculateAndUpdateHull(); } catch (undefined) {} finalize = function() { + $("#download-project-file").attr("data-href", correctedPath); + console.info("Raw data download repointed to", correctedPath); _adp.skipRead = true; _adp.dataBu = _adp.projectData; if (skipSave === true) { diff --git a/js/admin.min.js b/js/admin.min.js index 284587f6..f9737ce8 100644 --- a/js/admin.min.js +++ b/js/admin.min.js @@ -1,2 +1,2 @@ -var _7zHandler,alertBadProject,bootstrapTransect,bootstrapUploader,checkInitLoad,copyMarkdown,createOverflowMenu,csvHandler,dataAttrs,dataFileParams,delayFimsRecheck,domainHost,excelDateToUnixTime,excelHandler,excelHandler2,finalizeData,getCanonicalDataCoords,getInfoTooltip,getProjectCartoData,getTableCoordinates,getUploadIdentifier,helperDir,imageHandler,kmlHandler,kmlLoader,loadCreateNewProject,loadEditor,loadProject,loadProjectBrowser,loadSUProfileBrowser,loadSUProjectBrowser,mapAddPoints,mapOverlayPolygon,mintBcid,mintExpedition,newGeoDataHandler,pointStringToLatLng,pointStringToPoint,popManageUserAccess,populateAdminActions,recalculateAndUpdateHull,remintArk,removeDataFile,renderValidateProgress,resetForm,revalidateAndUpdateData,saveEditorData,showAddUserDialog,showUnrestrictionCriteria,singleDataFileHelper,startAdminActionHelper,startEditorUploader,stopLoadBarsError,uploadedData,user,userEmail,userFullname,validateData,validateFimsData,validateTaxonData,verifyLoginCredentials,zipHandler,indexOf=[].indexOf||function(e){for(var a=0,t=this.length;a\n

Please be patient

\n

\n The internet is a bit slow right now. We're still verifying your credentials.\n

\n",$("main #main-body").html("
\n

Please be patient

\n

\n The internet is a bit slow right now. We're still verifying your credentials.\n

\n
"),!1})}catch(e){}try{verifyLoginCredentials(function(e){var a,t;return clearTimeout(o),t=!0===e.unrestricted?"":"",a="

\n Welcome, "+$.cookie(adminParams.domain+"_name")+" "+t+"\n

\n
\n
\n

Please be patient while the administrative interface loads.

\n
\n
",$("main #main-body").before(a),$(".fill-user-fullname").text($.cookie(adminParams.domain+"_fullname")),$("#restriction-badge").click(function(){return showUnrestrictionCriteria()}),checkInitLoad(function(){return populateAdminActions(),bindClicks()}),!1})}catch(e){e,$("main #main-body").html("

Application Error

There was an error in the application. Please refresh and try again. If this persists, please contact administration.

")}return!1},populateAdminActions=function(){var e,a,t,o,n;return n=uri.urlString+"admin-page.html",o={do:"home",prop:null},history.pushState(o,"Admin Home",n),$(".hanging-alert").remove(),a='\n \n Create New Project\n\n',t='\n \n Verify & Create Project\n',e=(_adp.isUnrestricted?a:t)+'\n \n \n Edit Existing Project\n \n \n \n View All My Projects\n ',$("#admin-actions-block").html(e),$("#show-actions").remove(),$("main #main-body").empty(),$("#new-project").click(function(){return loadCreateNewProject()}),$("#edit-project").click(function(){return loadEditor()}),$("#view-project").click(function(){return loadProjectBrowser()}),$("#create-placeholder").click(function(){return showUnrestrictionCriteria()}),verifyLoginCredentials(function(e){if(toInt(e.detail.userdata.su_flag).toBool()){console.info("NOTICE: This is an SUPERUSER Admin"),'\n \n \n (SU) Administrate All Projects\n\n\n \n \n (SU) Manage All Users\n',$("#admin-actions-block").append('\n \n \n (SU) Administrate All Projects\n\n\n \n \n (SU) Manage All Users\n');try{delay(500,function(){return setupDebugContext()})}catch(e){}$("#su-view-projects").click(function(){return loadSUProjectBrowser()}),$("#su-manage-users").click(function(){return loadSUProfileBrowser()})}return _adp.isUnrestricted=e.unrestricted,!0!==e.unrestricted&&($("#new-project").remove(),$("#create-placeholder").exists()||$("#edit-project").before(t),$("#create-placeholder").unbind().click(function(){return showUnrestrictionCriteria()})),!0!==e.unrestricted||$("#new-project").exists()||($("#create-placeholder").remove(),$("#new-project").exists()||$("#edit-project").before(a),$("#new-project").unbind().click(function(){return loadCreateNewProject()})),!1}),!1};try{(createOverflowMenu=function(){return checkLoggedIn(function(e){var a,t;return t='\n \n \n '+(a=e.status?' \n \n Account Settings\n\n\n \n Log Out\n':"")+'\n \n \n Data Dashboard\n \n \n \n Documentation\n \n \n \n Github\n \n \n About / Legal\n \n \n',$("#header-overflow-menu").remove(),$("header#header-bar .logo-container + p").append(t),isNull(a)||$("header#header-bar paper-icon-button[icon='icons:settings-applications']").remove(),bindClicks()}),!1})()}catch(e){}showUnrestrictionCriteria=function(){return startLoad(),verifyLoginCredentials(function(e){var a,t,o,n,r,i,s,l,c,d,p,u,m,g,f,h,b,v,y,w,_;return stopLoad(),m=e.unrestricted.toBool(),d=e.has_alternate.toBool(),w=e.detail.userdata.email_verified.toBool(),l=e.email_allowed.toBool(),d?(y=e.detail.userdata.alternate_email_verified.toBool(),c=(n=e.alternate_allowed.toBool())||l):c=l,h=toInt(e.detail.userdata.su_flag),f=toInt(e.detail.userdata.admin_flag),p=h.toBool()||f.toBool(),a="https://"+adminParams.domain+".org/"+adminParams.loginDir.slice(0,-1),r='',u='',o="
Verifiable email addresses can be from "+e.restriction_criteria.domains+" domains, but must end in: "+e.restriction_criteria.tlds+"",t=c?r+" Have an email in allowed TLDs / domains. "+o:d?u+" Neither your primary email or alternate email is in an allowed TLD / domain. Fix: Change your alternative email in Account Settings. "+o:u+" To create a new project, you must have a verifiable email address. Fix: Add an alternative email address in Account Settings. "+o,_=w?r+" Have a verified username":u+" Your primary email isn't verified. Fix: Verify it in Account Settings",d&&(y?v=r+" Your alternate email is verified":n&&(v=u+" Your alternate email isn't verified. Fix: Verify it in Account Settings")),v=isNull(v)?"":"
  • "+v+"
  • ",g="",p&&(g=r+" You're "+(h.toBool()?"a SuperUser":"an administrator")+". You're always unrestricted."),i="
    \n "+g+'\n \n

    \n Restricted accounts can't create projects.\n

    \n
    ",b=m?"Your account is unrestricted":"Your account is restricted",$("#restriction-summary").remove(),s='\n

    '+b+"

    \n \n "+i+'\n \n
    \n Close\n
    \n
    ',$("body").append(s),safariDialogHelper("#restriction-summary",0,function(){return console.info("Opened restriction summary dialog")}),!1}),!1},verifyLoginCredentials=function(a){var e;return e="hash="+$.cookie(adminParams.domain+"_auth")+"&secret="+$.cookie(adminParams.domain+"_secret")+"&dblink="+$.cookie(adminParams.domain+"_link"),$.post(adminParams.loginApiTarget,e,"json").done(function(e){if(!0===e.status)return"undefined"!=typeof _adp&&null!==_adp||(window._adp={}),_adp.isUnrestricted=e.unrestricted,a(e);console.error("Invalid login credentials, redirecting to login url");try{localStorage.lastLogin=JSON.stringify(e)}catch(e){}return goTo(e.login_url)}).fail(function(e,a){return $("main #main-body").html("

    Couldn't verify login

    There's currently a server problem. Try back again soon.

    "),console.log(e,a),!1}),!1},startAdminActionHelper=function(){return $("#admin-actions-block").empty(),$("#pib-wrapper-dashboard").remove(),'\n \n \n',$("#pib-wrapper-settings").after('\n \n \n'),$("#show-actions").click(function(){return $(this).tooltip("hide"),$(".tooltip").tooltip("hide"),populateAdminActions()})},getInfoTooltip=function(e){return null==e&&(e="No Message Provided"),'
    \n \n
    '},alertBadProject=function(e){return e=null!=e?"project "+e:"this project",stopLoadError("Sorry, "+e+" doesn't exist"),!1},loadCreateNewProject=function(){var a,t,e,o,n,r,i,s,l;l=uri.urlString+"admin-page.html#action:create-project",i={do:"action",prop:"create-project"},history.pushState(i,"Create New Project",l),startAdminActionHelper(),t='

    Project Title

    \n\n'+getInfoTooltip("A descriptive title is most useful. Tell us the main focus of the project and whether a monitoring effort or project that just occurred in the Spring of 2015.")+'\n

    Project Parameters

    \n
    \n
    \n \n '+getInfoTooltip("Bd, Bsal, or other. If empty, we'll take it from your data.")+'\n \n \n '+getInfoTooltip("For example, specific Bd strains which have been sequenced JEL423, JAM81, if known")+'\n \n '+getInfoTooltip("E.g. a DOI or other reference")+'\n \n '+getInfoTooltip("Publication DOI citing these datasets may be added here.")+'\n

    Lab Parameters

    \n \n \n '+getInfoTooltip("This will be the identity used for the project citation")+'\n \n \n '+getInfoTooltip("This will be the identity suggested for technical communications about the project")+'\n \n \n '+getInfoTooltip("Name or PI responsible for lab results")+'\n '+getInfoTooltip("Of project PI. e.g., UC Berkeley")+'\n

    Project Notes

    \n '+getInfoTooltip("Project notes or brief abstract; accepts Markdown ")+'\n \n
    \n
    \n

    Data Permissions

    \n
    \n Private Dataset\n Public Dataset\n '+getInfoTooltip("this will be the setting for all data uploaded to this Project")+'\n
    \n\n

    Project Area of Interest

    \n
    \n

    \n This represents the approximate collection region for your samples.\n
    \n \n The last thing you do (search, build a locality, or upload data) will be your dataset\'s canonical locality.\n .\n

    \n Locality Name\n Coordinate List\n
    \n

    \n
    \n
    \n
    \n

    \n You may also click on the map to outline a region of interest, then click "Build Map" below to calculate a locality.\n

    \n

    \n \n \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n My project already has data\n
    \n
    \n
    \n
    \n
    \n

    Uploading your project data

    \n

    Drag and drop as many files as you need below.

    \n

    \n Please note that the data must have a header row,\n and the data must have the columns decimalLatitude, decimalLongitude, and coordinateUncertaintyInMeters. Your project must also be titled before uploading data.\n

    \n \n \n
    \n
    \n
    \n

    Project Data Summary

    \n

    Calculated Data Parameters

    \n \n \n \n \n \n \n

    Species in dataset

    \n \n

    Download Parsed Data

    \n
    \n
    \n
    \n
    \n \n \n
    \n
    ',$("main #main-body").append(t);try{$("#project-title").blur(function(){return p$(this).value.toLowerCase().replace(/ *b(sal|d\W) *|(19|20)[0-9]{2}|\s+\W|\s+(for|the|and|of|in|from|a|an)\s+/gim," ").replace(/ /gm," ").trim().split(" ").length<=3&&bsAlert("Your title seems very short/generic. Read it again, and make sure it is both unique and descriptive."),!1})}catch(e){console.warn("Couldn't set up blur event - "+(a=e).message),console.warn(a.stack)}mapNewWindows();try{for(r=$("paper-input[required]"),o=0,n=r.length;o\n

    ",$("#computed-locality").remove(),$("#using-computed-locality").remove(),$("#transect-input-container").after(t),!1})}),$("#reset-map-builder").click(function(){delete window.mapBuilder,$("#init-map-build").attr("disabled","disabled"),$("#init-map-build .points-count").text(window.mapBuilder.points.length);try{p$("google-map").clear()}catch(e){}return $("google-map google-map-marker").remove(),$("google-map google-map-poly").remove()}),s=p$("#project-notes").textarea,$(s).keyup(function(){return p$("#note-preview").markdown=$(this).val()}),bootstrapUploader(),bootstrapTransect(),$("#has-data").on("iron-change",function(){return $(this).get(0).checked?($(".data-section").removeAttr("hidden"),$(".label-with-data").removeAttr("hidden")):($(".data-section").attr("hidden","hidden"),$(".label-with-data").attr("hidden","hidden"))}),$("#data-encumbrance-toggle").on("iron-change",function(){var e;return e=p$("#data-encumbrance-toggle").checked?' Save Data & Create Public Project':' Save Data & Create Private Project',$("#upload-data").html(e)}),console.log("Getting location, prerequisite to setting up map ..."),getLocation(function(){var e;_adp.currentLocation=new Point(window.locationData.lat,window.locationData.lng),e={bsGrid:""},console.log("Location fetched, setting up map ..."),createMap2(null,e);try{return delay(500,function(){return setupDebugContext()})}catch(e){}}),bindClicks(),!1},finalizeData=function(z,J){var e,a,t,o,n,r;null==z&&(z=!1),startLoad();try{return a=!0,$("[required]").each(function(){var e;try{if(e=$(this).val(),isNull(e))return $(this).get(0).focus(),a=!1}catch(e){}}),a?(e=$.cookie(adminParams.domain+"_link"),isNull(_adp.projectId)&&(_adp.projectId=md5(""+geo.dataTable+e+Date.now())),r=p$("#project-title").value,(null!=dataFileParams?dataFileParams.hasDataFile:void 0)&&-1===dataFileParams.filePath.search(helperDir)&&(dataFileParams.filePath=""+helperDir+dataFileParams.filePath),o=null!=(n=null!=dataFileParams?dataFileParams.filePath:void 0)?n:null,mintBcid(_adp.projectId,o,r,function(e){var a,t,o,n,r,i,b,s,l,c,d,v,p,u,m,g,f,h,y,w,_,j,k,x,P,D,S,C,A,L,T,E,I,O,N,M,F,B,U,H,R;try{if(!e.status)return console.error(e.error),bsAlert(e.human_error,"danger"),stopLoadError(e.human_error),!1;if(dataAttrs.ark=e.ark,null==dataAttrs.data_ark&&(dataAttrs.data_ark=[]),dataAttrs.data_ark.push(e.ark+"::"+dataFileParams.fileName),k={},z)k=_adp.projectData;else for(x=$(".project-field"),p=0,u=x.length;p"+k.project_id+" created","success"),e=(new Date).toLocaleString(),o={action:"notify",subject:"Project '"+k.project_title+"' Created",body:"Project "+k.project_id+" ('"+k.project_title+"') created at "+e+" by "+$.cookie("amphibiandisease_fullname")+"<"+$.cookie("amphibiandisease_user")+">"},$.get(uri.urlString+"admin-api.php",buildArgs(o,"json")),$.get(uri.urlString+"recordMigrator.php"),stopLoad(),delay(1e3,function(){return loadEditor(_adp.projectId)}),toastStatusMessage("Data successfully saved to server")):(console.error(a.error.error),console.log(a),stopLoadError(a.human_error),bsAlert(a.human_error,"error"))}catch(e){b=e,stopLoadError("There was a verifying your save data");try{t=JSON.stringify(a)}catch(e){t="BAD_OBJECT"}try{bsAlert("There was a problem verifying your save data

    Application said: "+t+""+b.message+""+b.stack+"","error")}catch(e){}console.error("JavaScript error in save data callback! FinalizeData said: "+b.message),console.warn(b.stack)}return!1}).fail(function(e,a){return stopLoadError("There was a problem saving your data. Please try again"),!1})},console.info("Checking locality ..."),null==geo.computedLocality&&dataFileParams.hasDataFile){if(dataFileParams.hasDataFile)return null==t&&(t=getMapCenter(geo.boundingBox)),console.info("Computing locality with reverse geocode from",t,geo.boundingBox),geo.reverseGeocode(t.lat,t.lng,geo.boundingBox,function(e){return console.info("Computed locality "+e),_adp.locality=e,j()});try{_adp.locality=p$("#locality-input").value}catch(e){_adp.locality=""}return console.warn("How did we get to this state? No locality precomputed, no data file"),j()}if(null!=geo.computedLocality)console.info("Already have locality"),_adp.locality=geo.computedLocality;else try{console.info("Took written locality"),_adp.locality=p$("#locality-input").value}catch(e){console.info("Can't figure out locality"),_adp.locality=""}return dataFileParams.hasDataFile?j():mintExpedition(_adp.projectId,null,function(){return j()})}catch(e){return b=e,stopLoadError("There was a problem with the application. Please try again later. (E-003)"),console.error("JavaScript error in saving data (E-003)! FinalizeData said: "+b.message),console.warn(b.stack)}})):(stopLoadError("Please fill out all required fields"),!1)}catch(e){t=e,stopLoadError("There was a problem with the application. Please try again later. (E-004)");try{bsAlert("There was a problem with the application. Please try again later. (E-004)

    Application said: "+t.message+""+t.stack+"","error")}catch(e){}return console.error("JavaScript error in saving data (E-004)! FinalizeData said: "+t.message),console.warn(t.stack)}},resetForm=function(){return foo()},getTableCoordinates=function(e){return null==e&&(e="tdf0f1bc730325de59d48a5c80df45931_6d6d454828c05e8ceea03c99cc5f547e52fcb5fb"),!1},pointStringToLatLng=function(e,a){var t,o,n;return null==a&&(a=!1),e.search(!1)?(n=e.slice(6,-1).split(" "),o=1===(t=90\n \n Location Found: '+a[0].formatted_address+"\n"),s='

    \n Computed locality: '+a[0].formatted_address+'\n

    \n
    \n

    \n This is your currently active locality. Entering points below will take priority over this.\n

    \n
    ',$("#computed-locality").remove(),$("#using-computed-locality").remove(),$("#transect-input-container").after(s),$("#locality-lookup-result .lookup-name").text(a[0].formatted_address),_adp.locality=a[0].formatted_address,d=a[0].geometry.location,l=d.lat(),c=d.lng(),r=a[0].geometry.viewport;try{t=r.R,o=r.j,n={nw:[t.j,o.R],ne:[t.j,o.j],se:[t.R,o.R],sw:[t.R,o.j],north:t.j,south:t.R,east:o.j,west:o.R}}catch(e){console.warn("Danger: There was an error calculating the bounding box ("+(i=e).message+")"),console.warn(i.stack),console.info("Got bounds",r),console.info("Got geometry",a[0].geometry)}return console.info("Got bounds: ",[l,c],n),geo.boundingBox=n,loadJS("https://cartodb-libs.global.ssl.fastly.net/cartodb.js/v3/3.15/cartodb.js",function(){return geo.renderMapHelper(n,l,c)},!1)}return stopLoadError("Couldn't find location: "+e)})},geo.renderMapHelper=function(e,a,t){var o,n,r,i;if(null==e&&(e=geo.boundingBox),startLoad(),null==("undefined"!=typeof google&&null!==google?google.maps:void 0))return window.recallMapHelper=function(){return geo.renderMapHelper(e,a,t)},loadJS("https://maps.googleapis.com/maps/api/js?key="+gMapsApiKey+"&callback=recallMapHelper"),!1;try{return $("#carto-map-container").empty(),n={selector:"#carto-map-container",bsGrid:""},$(n.selector).empty(),i=function(){return stopLoad(),!1},null!=geo.dataTable?getCanonicalDataCoords(geo.dataTable,n,function(){return i()}):(n.boundingBox=e,r=new Point(a,t),createMap2([r],n,function(){return i()}))}catch(e){return console.error("There was an error rendering the map - "+(o=e).message),stopLoadError("There was an error rendering the map - "+o.message)}},t=function(){return null==("undefined"!=typeof google&&null!==google?google.maps:void 0)?loadJS("https://maps.googleapis.com/maps/api/js?key="+gMapsApiKey+"&callback=geocodeLookupCallback"):geocodeLookupCallback(),!1},(e=function(){var e,a;return p$("#transect-input-toggle").checked?(e="Please input a list of coordinates, in the form lat, lng, with one set on each line. Please press enter to insert a new line after your last coordinate.",a=''):(e="Please enter a name of a locality",a=' '),$("#transect-instructions").html(e),$("#transect-input-container").html(a),p$("#transect-input-toggle").checked?$(p$("#coord-input").textarea).keyup(function(e){var a,t,o,n,r,i,s,l,c,d,p,u,m,g;if(13===(e.keyCode?e.keyCode:e.which)&&3<(g=$(p$("#coord-input").textarea).val()).split("\n").length){for(r=[],i=g.split("\n"),console.info("Raw coordinate info:",i),c=0,d=i.length;c\n '+c.genus+" "+c.specificepithet+" "+c.infraspecificepithet+" collected on "+c.dateidentified+"\n

    \n

    \n Status:\n Sampled by "+c.samplemethod+", disease status "+c.diseasedetected+" for "+c.diseasetested+"\n

    "},r.infoWindow=f,t.push(r),n.push(f)}if(dataAttrs.coords=t,dataAttrs.markerInfo=n,console.info("Calling back with",t,y),"function"==typeof w)return w(t,y)}).fail(function(e,a){return null!=(null!=dataAttrs?dataAttrs.coords:void 0)?w(dataAttrs.coords,y):(stopLoadError("Couldn't get bounding coordinates from data"),console.error("No valid coordinates accessible!"))})}).fail(function(e,a){return!1})}),!1},getUploadIdentifier=function(){var e,a,t;if(isNull(_adp.uploadIdentifier)){if(isNull(_adp.projectId)){if(e=$.cookie(adminParams.domain+"_link"),isNull(_adp.projectIdentifierString)){try{t=isNull(p$("#project-title").value)?randomString(16):p$("#project-title").value}catch(e){t=randomString(16)}a="t"+md5(t+e),_adp.projectIdentifierString=a}_adp.projectId=md5(""+a+e+Date.now())}_adp.uploadIdentifier=md5(""+user+_adp.projectId)}return _adp.uploadIdentifier},bootstrapUploader=function(e,a,t){var o,n;return null==e&&(e="file-uploader"),null==a&&(a="col-md-4"),n="#"+e,$.cookie(adminParams.domain+"_link"),getUploadIdentifier(),_adp.projectIdentifierString,$(n).exists()||(o='
    \n

    Tap the button to upload a file

    \n \n
    ',$("main #uploader-container-section").append(o),console.info("Appended upload form"),$(n).submit(function(e){return e.preventDefault(),e.stopPropagation(),!1})),verifyLoginCredentials(function(){var e;return null==window.dropperParams&&(window.dropperParams={}),window.dropperParams.dropTargetSelector=n,window.dropperParams.uploadPath="uploaded/"+getUploadIdentifier()+"/",e=!0===window.dropperParams.hasInitialized,loadJS("helpers/js-dragdrop/client-upload.min.js",function(){if(console.info("Loaded drag drop helper"),e){console.info("Reinitialized dropper");try{window.dropperParams.initialize()}catch(e){console.warn("Couldn't reinitialize dropper!")}}if(window.dropperParams.postUploadHandler=function(e,a){var t,o,n,r,i,s,l,c;if(window.dropperParams.dropzone.removeAllFiles(),"object"!=typeof a)return console.error("Dropzone returned an error - "+a),toastStatusMessage("There was a problem with the server handling your image. Please try again."),!1;if(!0!==a.status)return null==a.human_error&&(a.human_error="There was a problem uploading your image."),toastStatusMessage(""+a.human_error),console.error("Error uploading!",a),!1;try{switch(console.info("Server returned the following result:",a),console.info("The script returned the following file information:",e),s="helpers/js-dragdrop/uploaded/"+getUploadIdentifier()+"/",o=a.full_path.split("/").pop(),c=a.wrote_thumb,i=a.mime_provided.split("/")[0],r=a.mime_provided.split("/")[1],n=e.size<5242880||"image"!==i?""+s+a.wrote_file:""+s+c,l=function(){switch(i){case"image":return'
    \n \'Uploaded\n

    \n '+e.name+" -> "+o+'\n (\n Original Image\n )\n

    \n
    ';case"audio":return'
    \n \n

    \n '+e.name+" -> "+o+'\n (\n Original Media\n )\n

    \n
    ';case"video":return'
    \n \n

    \n '+e.name+" -> "+o+'\n (\n Original Media\n )\n

    \n
    ';default:return'
    \n \n

    '+e.name+" -> "+o+"

    \n
    "}}(),$(window.dropperParams.dropTargetSelector).before(l),$("#validator-progress-container").remove(),n.slice(0),t=n.slice(0).split(".").pop(),i){case"application":switch(console.info("Checking "+r+" in application"),r){case"vnd.openxmlformats-officedocument.spreadsheetml.sheet":case"vnd.ms-excel":return excelHandler(n);case"vnd.ms-office":switch(t){case"xls":return excelHandler(n);default:return stopLoadError("Sorry, we didn't understand the upload type."),!1}break;case"zip":case"x-zip-compressed":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"===e.type||"xlsx"===t?excelHandler(n):"kmz"===t?kmlHandler(n):zipHandler(n);case"x-7z-compressed":return _7zHandler(n);case"vnd.google-earth.kml+xml":case"vnd.google-earth.kmz":case"xml":return"kml"===t||"kmz"===t?kmlHandler(n):(console.warn("Non-KML xml"),allError("Sorry, we can't processes files of type application/"+r),!1);default:return console.warn("Unknown mime type application/"+r),allError("Sorry, we can't processes files of type application/"+r),!1}break;case"text":return csvHandler(n);case"image":return imageHandler(n)}}catch(e){return e,toastStatusMessage("Your file uploaded successfully, but there was a problem in the post-processing.")}},"function"==typeof t)return t()}),!1})},singleDataFileHelper=function(e,a){if("function"!=typeof a)return console.error("Second argument must be a function"),!1;if(!0===dataFileParams.hasDataFile&&e!==dataFileParams.filePath){try{$("#bs-alert").remove()}catch(e){}return $("#single-data-file-modal").exists()&&$("#single-data-file-modal").remove(),'\n

    You can only have one primary data file

    \n
    \n Continuing will remove your previous one\n
    \n
    \n Cancel Upload\n Replace Previous\n
    \n
    ',$("body").append('\n

    You can only have one primary data file

    \n
    \n Continuing will remove your previous one\n
    \n
    \n Cancel Upload\n Replace Previous\n
    \n
    '),$("#cancel-parse").click(function(){return removeDataFile(e,!1),p$("#single-data-file-modal").close(),!1}),$("#overwrite").click(function(){return removeDataFile(),p$("#single-data-file-modal").close(),a()}),safariDialogHelper("#single-data-file-modal")}return a()},excelHandler=function(t,e,o){var a,n,r,i,s,l,c,d;null==e&&(e=!0),startLoad(),$("#validator-progress-container").remove(),renderValidateProgress(),i=helperDir+"excelHelper.php",-1!==(n=t).search(helperDir)&&(console.info("removing '"+helperDir+"'"),n=t.slice(helperDir.length)),console.info("Pinging for "+n),a="action=parse&path="+n+"&sheets=Samples",r=!1;try{for(d=$("paper-input[required]"),l=0,c=d.length;l, ")+"",bsAlert(y,"danger"),console.info("Missing: ",null!=S.decimalLatitude,null!=S.decimalLongitude,null!=S.coordinateUncertaintyInMeters),removeDataFile(),!1;if(!(isNumber(S.decimalLatitude)&&isNumber(S.decimalLongitude)&&isNumber(S.coordinateUncertaintyInMeters)))return toastStatusMessage("Data has invalid entries for geo columns. Please be sure they're all numeric and try again."),removeDataFile(),!1;D=Object.size(e);try{p$("#samplecount").value=D}catch(e){}if(isNull($("#project-disease").val()))try{p$("#project-disease").value=S.diseaseTested}catch(e){}j={},dataAttrs.coords=[],dataAttrs.coordsFull=[],dataAttrs.fimsData=[],u={},toastStatusMessage("Please wait, parsing your data"),$("#data-parsing").removeAttr("indeterminate");try{p$("#data-parsing").max=D}catch(e){}for(_ in Date.now(),N=[],d=[],e){for(n in P=e[_],k=toInt(_)+1,T={},O=[],P){if(M=P[n],n=n.trim(),0<=indexOf.call(O,n))return console.error("There was a duplicate column '"+n+"'",O),stopLoadBarsError(null,"You have at least one duplicate column '"+n+"'. Ensure all your columns are unique."),!1;switch(A=!1,n){case"ContactName":case"basisOfRecord":case"occurrenceID":case"institutionCode":case"collectionCode":case"labNumber":case"originalsource":case"datum":case"georeferenceSource":case"depth":case"Collector2":case"Collector3":case"verbatimLocality":case"Habitat":case"Test_Method":case"eventRemarks":case"quantityDetected":case"dilutionFactor":case"cycleTimeFirstDetection":if("string"==typeof M)try{M=(M=(M=M.replace(/;/gim,";")).replace(/'/gim,"'")).replace(/"/gim,""")}catch(e){console.warn("Couldn't replace quotes for this:",M)}u[n]=M,A=!0;break;case"specimenDisposition":n="sampleDisposition";break;case"sampleType":n="sampleMethod";break;case"elevation":n="alt";break;case"dateCollected":case"dateIdentified":if(n="dateIdentified",L=excelDateToUnixTime(M,!0),!isNumber(L))return console.error("This row (#"+k+") has a non-date value ! ("+M+" = "+L+")"),stopLoadBarsError(null,"Detected an invalid date '"+M+"' at row #"+k+". Check your dates!"),!1;if(s=new Date(L),L"+s.toDateString()+" at row #"+k+". Check your dates!"),!1;if(L>Date.now())return console.error("This row (#"+k+") has a date ("+M+" = "+L+") after today!"),stopLoadBarsError(null,"Detected a future date '"+M+"' at row #"+k+". Check your dates!"),!1;(c=s.getUTCDate())<10&&(c="0"+c),(w=s.getUTCMonth()+1)<10&&(w="0"+w),o=s.getUTCFullYear()+"-"+w+"-"+c;break;case"fatal":o=M.toBool();break;case"decimalLatitude":case"decimalLongitude":case"alt":case"coordinateUncertaintyInMeters":if(!isNumber(M))return stopLoadBarsError(null,"Detected an invalid number for "+n+" at row "+k+" ("+M+")"),!1;if("decimalLatitude"===n&&(M<-90||90"+M+" at row "+k+"

    Valid latitudes are between 90 and -90."),!1;if("decimalLongitude"===n&&(M<-180||180"+M+" at row "+k+"

    Valid latitudes are between 180 and -180."),!1;if("coordinateUncertaintyInMeters"===n&&M<=0)return stopLoadBarsError(null,"Coordinate uncertainty must be >= 0 at row "+k),!1;o=toFloat(M);break;case"diseaseDetected":if(isBool(M))o=M.toBool();else try{o="negative"!==M.trim().toLowerCase()&&("positive"===M.trim().toLowerCase()||"NO_CONFIDENCE")}catch(e){o="NO_CONFIDENCE"}break;case"sex":try{M="m"===(M=M.trim().toLowerCase()).slice(0,1)?"male":"f"===M.slice(0,1)?"female":"not determined"}catch(e){M="not determined"}break;case"sampleId":try{"n/a"===(I=M.trim()).toLowerCase()&&(I=""),o=I=I.replace(/^([a-zA-Z]+) (\d+)$/gm,"$1$2")}catch(e){o=M}indexOf.call(N,o)<0?N.push(o):indexOf.call(d,o)<0&&d.push(o);break;default:try{o=M.trim()}catch(e){o=M}}A||(T[n]=o)}r={lat:T.decimalLatitude,lng:T.decimalLongitude,alt:T.alt,uncertainty:T.coordinateUncertaintyMeters},i=new Point(r.lat,r.lng),dataAttrs.coords.push(i),dataAttrs.coordsFull.push(r),dataAttrs.fimsData.push(u);try{T.fimsExtra=JSON.stringify(u)}catch(e){console.warn("Couldn't store FIMS extra data",u)}j[_]=T,0===modulo(_,500)&&0<_&&(toastStatusMessage("Processed "+_+" rows ..."),console.log("Processed "+_+" rows ..."));try{p$("#data-parsing").value=_+1}catch(e){}}try{console.log("Basic validation passed"),isNull(d)||bsAlert("Warning: the following field IDs all had duplicates:
    "+d+"
    We strongly recommend unique IDs.","warning")}catch(e){}isNull(_adp.projectIdentifierString)?(x="t"+md5(p$("#project-title").value+a+Date.now()),_adp.projectIdentifierString=x):x=_adp.projectIdentifierString;try{f={downloadFile:"cleaned-dataset-"+Date.now()+".csv",selector:"#download-server-parsed-data"},downloadCSVFile(j,f),window.parsedData=j,_adp.cleanedAndParsedData=j}catch(e){}for(b in h=function(){var e,a,t,o,n,r,i;for(t={},i="",o=a=0,n=(r=sortPoints(dataAttrs.coords)).length;o'+(""+c.response.original_taxon.slice(0,1).toUpperCase()+c.response.original_taxon.slice(1))+"' was a synonym in the AmphibiaWeb database. It was automatically converted to '"+u+"' below. See the AmphibiaWeb entry \n',$("#species-list").before(i)),isNull(c.subspecies)||(u+=" "+c.subspecies),indexOf.call(d,u)<0&&(0biscicol.org FIMS requirements')}return!1},excelDateToUnixTime=function(e,a){var t,o,n;null==a&&(a=!1),n=(new Date).getUTCFullYear();try{if(!isNumber(e)){if(t=Date.parse(e),isNumber(t))return t;throw"Bad date error"}if(1863<=e&&e<=n)o=Date.parse(e+"-01-03");else if(0 "+o),"Bad Number Error"}else o=Date.parse(e)}catch(e){o=!a&&Date.now()}return o},renderValidateProgress=function(e,a){var t;return null==e&&(e="#file-uploader-form"),null==a&&(a=!1),t='
    \n \n \n \n \n

    \n \n
    ',$("#validator-progress-container").exists()||($(e).after(t),$("#cancel-new-upload").click(function(){return cancelAsyncOperation(this)})),!!a&&t},checkInitLoad=function(e){var a,t,o;if($("#please-wait-prefill").remove(),o=uri.o.param("id"),isNull(o))if(a="string"==typeof e?e:"object"==typeof e?e.do+":"+e.prop:uri.o.attr("fragment"),isNull(a))"function"==typeof e&&e();else switch(t=a.split(":"),console.info("Looking at fragment",a,t),t[0]){case"edit":loadEditor(t[1]);break;case"action":switch(t[1]){case"show-editable":loadEditor();break;case"create-project":loadCreateNewProject();break;case"show-viewable":loadProjectBrowser();break;case"show-su-viewable":loadSUProjectBrowser();break;case"show-su-profiles":loadSUProfileBrowser()}break;case"home":populateAdminActions()}else loadEditor(o);return!1},window.onpopstate=function(e){return console.log("State popped",e,e.state),checkInitLoad(e.state),!1},$(function(){$("#next").exists()&&$("#next").unbind().click(function(){return openTab(adminParams.adminPageUrl)}),loadJS("bower_components/bootstrap/dist/js/bootstrap.min.js",function(){return $("body").tooltip({selector:"[data-toggle='tooltip']"})}),checkFileVersion(!1,"js/admin.min.js"),$("paper-icon-button[icon='icons:dashboard']").removeAttr("data-href").unbind("click").click(function(){return populateAdminActions()});try{return checkFileVersion(!0,"js/kml.min.js")}catch(e){}}),kmlLoader=function(t,o){var e,a,n,r,i;try{if("object"==typeof t)t=(a=t).path;else try{a=JSON.parse(t),t=a.path}catch(e){try{a=JSON.parse(deEscape(t)),t=a.path}catch(e){511\n')+"\n",!$("#auth-block").exists())return console.warn("Couldn't find an authorization block to render the KML map in!"),!1;$("#auth-block").append(n),_adp.mapRendered=!0}return loadJS(e,function(){return initializeParser(null,function(){return loadKML(t,function(){var a,e;try{if(e=geo.kml.parser.docsByUrl[t],isNull(e)&&(t="/"+t,e=geo.kml.parser.docsByUrl[t],isNull(e)&&(console.warn("Could not resolve KML by url, using first doc"),e=geo.kml.parser.docs[0])),isNull(e))return allError("Bad KML provided"),!1;console.debug("Using parsed data from path '"+t+"'",e),"function"==typeof o?o(e):console.info("kmlHandler wasn't given a callback function"),stopLoad()}catch(e){a=e,allError("There was a importing the data from this KML file"),console.warn(a.message),console.warn(a.stack)}return!1}),!1}),!1}),!1},loadEditor=function(e){var u,te;return startAdminActionHelper(),u=function(ae){var e,a;return startAdminActionHelper(),a=uri.urlString+"admin-page.html#edit:"+ae,e={do:"edit",prop:ae},history.pushState(e,"Editing #"+ae,a),startLoad(),window.projectParams={},window.projectParams.pid=ae,verifyLoginCredentials(function(e){var Q,ee,a;return a=e.detail,user=a.uid,Q="perform=get&project="+(ae=encodeURIComponent(ee=ae)),_adp.currentAsyncJqxhr=$.post(adminParams.apiTarget,Q,"json").done(function(e){var a,t,o,n,r,i,s,l,c,d,p,u,m,g,f,h,b,v,y,w,_,j,k,x,P,D,S,C,A,L,T,E,I,O,N,M,F,B,U,H,R,z,J,q,W,G,V,Y,K,Z,X;try{if(console.info("Server said",e),!0!==e.status)return null==(f=null!=(B=e.human_error)?B:e.error)&&(f="Unidentified Error"),stopLoadError("There was a problem loading your project ("+f+")"),console.error("Couldn't load project! (POST OK) Error: "+e.error),console.warn("Attempted",adminParams.apiTarget+"?"+Q),!1;if(!0!==e.user.has_edit_permissions)return e.user.has_view_permissions||!0===e.project.public.toBool()?(loadProject(ee,"Ineligible to edit "+ee+", loading as read-only"),delay(1e3,function(){return loadProject(ae)})):alertBadProject(ee),!1;for((M=e.project).access_data.total=Object.toArray(M.access_data.total),M.access_data.total.sort(),M.access_data.editors_list=Object.toArray(M.access_data.editors_list),M.access_data.viewers_list=Object.toArray(M.access_data.viewers_list),M.access_data.editors=Object.toArray(M.access_data.editors),M.access_data.viewers=Object.toArray(M.access_data.viewers),console.info("Project access lists:",M.access_data),_adp.projectData=M,_adp.originalProjectId=M.project_id,_adp.fetchResult=e,V="",y=[],U=M.access_data.total,k=0,x=U.length;k':0<=indexOf.call(M.access_data.editors_list,user)?j='':0<=indexOf.call(M.access_data.viewers_list,user)&&(j=''),V+='\n '+user+'\n '+j+"\n"}j=M.public.toBool()?'':'',F=M.public.toBool()?"\x3c!-- This project is already public --\x3e":e.user.is_author?'
    \n \n \n Make this project public\n Once saved, this cannot be undone\n
    ':"\x3c!-- This user does not have permission to toggle the public state of this project --\x3e",l=e.user.has_edit_permissions?"":"readonly",a=M.includes_anura.toBool()?"checked disabled":"disabled",r=M.includes_caudata.toBool()?"checked disabled":"disabled",v=M.includes_gymnophiona.toBool()?"checked disabled":"disabled";try{n=JSON.parse(deEscape(M.carto_id))}catch(e){console.error("Couldn't parse the carto JSON!",M.carto_id),stopLoadError("We couldn't parse your data. Please try again later."),n={}}"";try{o=Object.toArray(n.bounding_polygon)}catch(e){o=null}c={boundingBox:o,classes:"carto-data map-editor",bsGrid:"",skipPoints:!1,skipHull:!1,onlyOne:!0},geo.mapOptions=c,null==(null!=(H=n.bounding_polygon)?H.paths:void 0)&&(b='\n'),null==b&&(b=""),geo.googleMapWebComponent=b,m=e.user.is_author?'
    \n Delete this project\n
    ':"",A=isNull(M.sample_notes)?"*No notes for this project*":M.sample_notes.unescape(),O='

    Project Notes

    \n\n\n\n
    \n