public function find($sync, $filename = null, $token = null, $minW = -1, $minH = -1)
 {
     //check cache
     $cacheKey = $token === null ? json_encode(md5($filename)) : $token;
     $cached = $this->_db->get($cacheKey);
     if ($cached !== null) {
         return json_decode($cached);
     }
     if ($sync === false || $filename === false) {
         return ['token' => $cacheKey];
     }
     $image = $this->loadGDImage($filename);
     //perform web search
     $parts = explode('://', $filename);
     $isFile = count($parts) === 1 || $parts[0] === 'file';
     if ($isFile) {
         $post = ['image_url' => '', 'encoded_image' => new \CURLFile(str_replace('file://', '', $filename)), 'image_content' => '', 'filename' => '', 'hl' => 'en'];
         $res = $this->curl('https://images.google.com/searchbyimage/upload', $post, true);
         preg_match('/^Location: (.+)\\n/Usmi', $res, $m);
         $resultsUrl = trim($m[1]);
     } else {
         $res = $this->curl('https://images.google.com/searchbyimage?image_url=' . urlencode($filename) . '&encoded_image=&image_content=&filename=&hl=en', [], true);
         preg_match('/^Location: (.+)\\n/Usmi', $res, $m);
         $resultsUrl = trim($m[1]);
     }
     $imageUrls = array_slice($this->search($resultsUrl), 0, static::MAX_LOAD_IMAGES);
     //check found files
     $result = $this->process($image, $imageUrls, $minW, $minH);
     $this->_db->set($cacheKey, json_encode($result));
     return $result;
 }