@@ -265,7 +265,8 @@ public function getGitHubRepos(string $username): array
265265 if (isset ($ http_response_header )) {
266266 foreach ($ http_response_header as $ header ) {
267267 if (stripos ($ header , 'X-RateLimit-Remaining: ' ) === 0 ) {
268- $ remaining = intval (trim (substr ($ header , 21 )));
268+ // Extract value after "X-RateLimit-Remaining: " (22 chars + space = 23)
269+ $ remaining = intval (trim (substr ($ header , 23 )));
269270 if ($ remaining <= 5 ) {
270271 // Using warning level for rate limit notifications
271272 \rex_logger::factory ()->log (\Psr \Log \LogLevel::WARNING ,
@@ -351,6 +352,15 @@ protected function isValidUrl(string $url): bool
351352 curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , true );
352353 curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
353354
355+ // Add Authorization header if token is available
356+ $ token = $ this ->addon ->getConfig ('github_token ' );
357+ $ host = parse_url ($ url , PHP_URL_HOST );
358+ if ($ token && $ host && ($ host === 'github.com ' || str_ends_with ($ host , '.github.qkg1.top ' ))) {
359+ curl_setopt ($ ch , CURLOPT_HTTPHEADER , [
360+ 'Authorization: Bearer ' . $ token
361+ ]);
362+ }
363+
354364 curl_exec ($ ch );
355365 $ httpCode = curl_getinfo ($ ch , CURLINFO_HTTP_CODE );
356366 $ error = curl_error ($ ch );
@@ -389,10 +399,20 @@ protected function downloadFile(string $url, string $destination): bool
389399 curl_setopt ($ ch , CURLOPT_USERAGENT , 'REDAXOZipInstall/2.2.1 ' );
390400 curl_setopt ($ ch , CURLOPT_SSL_VERIFYPEER , true );
391401 curl_setopt ($ ch , CURLOPT_SSL_VERIFYHOST , 2 );
392- curl_setopt ($ ch , CURLOPT_HTTPHEADER , [
402+
403+ $ headers = [
393404 'Accept: application/zip, application/octet-stream, */* ' ,
394405 'Cache-Control: no-cache '
395- ]);
406+ ];
407+
408+ // Add Authorization header if token is available
409+ $ token = $ this ->addon ->getConfig ('github_token ' );
410+ $ host = parse_url ($ url , PHP_URL_HOST );
411+ if ($ token && $ host && ($ host === 'github.com ' || str_ends_with ($ host , '.github.qkg1.top ' ))) {
412+ $ headers [] = 'Authorization: Bearer ' . $ token ;
413+ }
414+
415+ curl_setopt ($ ch , CURLOPT_HTTPHEADER , $ headers );
396416
397417 $ content = curl_exec ($ ch );
398418 $ httpCode = curl_getinfo ($ ch , CURLINFO_HTTP_CODE );
@@ -615,4 +635,52 @@ public function getAddonKeyFromUrl(string $url): ?string
615635 }
616636 return null ;
617637 }
638+
639+ /**
640+ * Get GitHub API Rate Limit
641+ *
642+ * @return array|null Returns array with limit, remaining, reset or null on error
643+ */
644+ public function getRateLimit (): ?array
645+ {
646+ $ token = $ this ->addon ->getConfig ('github_token ' );
647+
648+ $ headers = [
649+ 'User-Agent: REDAXOZipInstall/2.0 ' ,
650+ 'Accept: application/vnd.github.v3+json '
651+ ];
652+
653+ if ($ token ) {
654+ $ headers [] = 'Authorization: Bearer ' . $ token ;
655+ }
656+
657+ $ options = [
658+ 'http ' => [
659+ 'method ' => 'GET ' ,
660+ 'header ' => implode ("\r\n" , $ headers ),
661+ 'timeout ' => 5
662+ ]
663+ ];
664+
665+ $ context = stream_context_create ($ options );
666+
667+ try {
668+ $ response = @file_get_contents ('https://api.github.com/rate_limit ' , false , $ context );
669+
670+ if ($ response !== false ) {
671+ $ data = json_decode ($ response , true );
672+ if (isset ($ data ['rate ' ])) {
673+ return [
674+ 'limit ' => $ data ['rate ' ]['limit ' ],
675+ 'remaining ' => $ data ['rate ' ]['remaining ' ],
676+ 'reset ' => $ data ['rate ' ]['reset ' ]
677+ ];
678+ }
679+ }
680+ } catch (Exception $ e ) {
681+ // Ignore errors
682+ }
683+
684+ return null ;
685+ }
618686}
0 commit comments