From 99e56573796a9566f50902d679b4ff075c79db2e Mon Sep 17 00:00:00 2001 From: Edmar Moretti Date: Wed, 1 Dec 2010 12:21:11 +0000 Subject: [PATCH] Implementação de comentários do usuário em uma camada --- admin/admin.db | Bin 67584 -> 0 bytes admin/index.html | 3 +++ admin/js/editormapfile.js | 8 +++++++- admin/php/classe_arvore.php | 1 - admin/php/conexao.php | 2 +- admin/php/criabanco.php | 14 ++++++++------ admin/php/editormapfile.php | 6 +++++- admin/php/sqlite.php | 4 ++-- admin/php/upgradebanco44_45.php | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ admin/php/xml.php | 22 ++++++++++++++++++++++ admin/rsscomentariostemas.php | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ admin/rsstemas.php | 1 - classesjs/classe_arvoredecamadas.js | 6 ++++-- classesjs/classe_arvoredetemas.js | 21 ++++++++++++++++++--- classesjs/classe_barradebotoes.js | 7 ++++--- classesjs/classe_i3geo.js | 83 ++++------------------------------------------------------------------------------- classesjs/classe_tema.js | 12 ++++++++++++ classesjs/dicionario.js | 7 +++++++ classesjs/dicionario_ajuda.js | 8 ++++++++ classesphp/classe_mapa.php | 6 +++++- classesphp/mapa_controle.php | 8 ++++---- classesphp/mapa_inicia.php | 10 ++++++++-- ferramentas/comentarios/index.php | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ guia_de_migracao.txt | 8 +++++++- imagens/redes_blogger.png | Bin 0 -> 2355 bytes imagens/redes_facebook.png | Bin 0 -> 2720 bytes imagens/redes_google.png | Bin 0 -> 6133 bytes imagens/redes_linkedin.png | Bin 0 -> 3738 bytes imagens/redes_myspace.png | Bin 0 -> 5722 bytes imagens/redes_oauth.png | Bin 0 -> 1454 bytes imagens/redes_openid.png | Bin 0 -> 1135 bytes imagens/redes_twitter.png | Bin 0 -> 4875 bytes imagens/redes_windowslive.png | Bin 0 -> 4081 bytes imagens/redes_wordpress.png | Bin 0 -> 3858 bytes interface/googlemaps.phtml | 2 ++ ms_configura.php | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/facebookoauth/callback.php | 19 +++++++++++++++++++ pacotes/facebookoauth/clearsessions.php | 13 +++++++++++++ pacotes/facebookoauth/config.php | 5 +++++ pacotes/facebookoauth/index.php | 28 ++++++++++++++++++++++++++++ pacotes/linkedinoauth/CHANGELOG.txt | 15 +++++++++++++++ pacotes/linkedinoauth/LICENSE.txt | 22 ++++++++++++++++++++++ pacotes/linkedinoauth/OAuth.php | 866 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/OAuthTests.xml | 13 +++++++++++++ pacotes/linkedinoauth/OAuth_TestServer.php | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/doc/design.txt | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/example/SimpleOAuthDataStore.php | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/example/access_token.php | 14 ++++++++++++++ pacotes/linkedinoauth/example/client.php | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/example/common.inc.php | 27 +++++++++++++++++++++++++++ pacotes/linkedinoauth/example/echo_api.php | 21 +++++++++++++++++++++ pacotes/linkedinoauth/example/index.php | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/example/request_token.php | 14 ++++++++++++++ pacotes/linkedinoauth/linkedin.php | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/testLinkedinOauth.php | 39 +++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/testWithAcessToken.php | 22 ++++++++++++++++++++++ pacotes/linkedinoauth/tests/Mock_OAuthBaseStringRequest.php | 12 ++++++++++++ pacotes/linkedinoauth/tests/Mock_OAuthDataStore.php | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php | 47 +++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthConsumerTest.php | 10 ++++++++++ pacotes/linkedinoauth/tests/OAuthRequestTest.php | 317 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthServerTest.php | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthSignatureMethodHmacSha1Test.php | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthSignatureMethodPlaintextTest.php | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthSignatureMethodRsaSha1Test.php | 43 +++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthTokenTest.php | 20 ++++++++++++++++++++ pacotes/linkedinoauth/tests/OAuthUtilTest.php | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/linkedinoauth/tests/common.php | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/openid/example-google.php | 23 +++++++++++++++++++++++ pacotes/openid/login.php | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/openid/openid.php | 743 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/openid/provider/example-mysql.php | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/openid/provider/example.php | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/openid/provider/provider.php | 833 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/DOCUMENTATION | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/LICENSE.txt | 22 ++++++++++++++++++++++ pacotes/twitteroauth/README.txt | 7 +++++++ pacotes/twitteroauth/callback.php | 41 +++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/clearsessions.php | 13 +++++++++++++ pacotes/twitteroauth/config.php | 13 +++++++++++++ pacotes/twitteroauth/connect.php | 23 +++++++++++++++++++++++ pacotes/twitteroauth/html.inc | 39 +++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/images/darker.png | 793 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/images/lighter.png | 793 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/index.php | 35 +++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/redirect.php | 32 ++++++++++++++++++++++++++++++++ pacotes/twitteroauth/test.php | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/twitteroauth/OAuth.php | 874 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pacotes/twitteroauth/twitteroauth/twitteroauth.php | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ testainstal.php | 3 ++- 90 files changed, 8682 insertions(+), 109 deletions(-) create mode 100644 admin/php/upgradebanco44_45.php create mode 100644 admin/rsscomentariostemas.php create mode 100644 ferramentas/comentarios/index.php create mode 100644 imagens/redes_blogger.png create mode 100644 imagens/redes_facebook.png create mode 100644 imagens/redes_google.png create mode 100644 imagens/redes_linkedin.png create mode 100644 imagens/redes_myspace.png create mode 100644 imagens/redes_oauth.png create mode 100644 imagens/redes_openid.png create mode 100644 imagens/redes_twitter.png create mode 100644 imagens/redes_windowslive.png create mode 100644 imagens/redes_wordpress.png create mode 100644 pacotes/facebookoauth/callback.php create mode 100644 pacotes/facebookoauth/clearsessions.php create mode 100644 pacotes/facebookoauth/config.php create mode 100644 pacotes/facebookoauth/index.php create mode 100644 pacotes/linkedinoauth/CHANGELOG.txt create mode 100644 pacotes/linkedinoauth/LICENSE.txt create mode 100644 pacotes/linkedinoauth/OAuth.php create mode 100644 pacotes/linkedinoauth/OAuthTests.xml create mode 100644 pacotes/linkedinoauth/OAuth_TestServer.php create mode 100644 pacotes/linkedinoauth/doc/design.txt create mode 100644 pacotes/linkedinoauth/example/SimpleOAuthDataStore.php create mode 100644 pacotes/linkedinoauth/example/access_token.php create mode 100644 pacotes/linkedinoauth/example/client.php create mode 100644 pacotes/linkedinoauth/example/common.inc.php create mode 100644 pacotes/linkedinoauth/example/echo_api.php create mode 100644 pacotes/linkedinoauth/example/index.php create mode 100644 pacotes/linkedinoauth/example/request_token.php create mode 100644 pacotes/linkedinoauth/linkedin.php create mode 100644 pacotes/linkedinoauth/testLinkedinOauth.php create mode 100644 pacotes/linkedinoauth/testWithAcessToken.php create mode 100644 pacotes/linkedinoauth/tests/Mock_OAuthBaseStringRequest.php create mode 100644 pacotes/linkedinoauth/tests/Mock_OAuthDataStore.php create mode 100644 pacotes/linkedinoauth/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php create mode 100644 pacotes/linkedinoauth/tests/OAuthConsumerTest.php create mode 100644 pacotes/linkedinoauth/tests/OAuthRequestTest.php create mode 100644 pacotes/linkedinoauth/tests/OAuthServerTest.php create mode 100644 pacotes/linkedinoauth/tests/OAuthSignatureMethodHmacSha1Test.php create mode 100644 pacotes/linkedinoauth/tests/OAuthSignatureMethodPlaintextTest.php create mode 100644 pacotes/linkedinoauth/tests/OAuthSignatureMethodRsaSha1Test.php create mode 100644 pacotes/linkedinoauth/tests/OAuthTokenTest.php create mode 100644 pacotes/linkedinoauth/tests/OAuthUtilTest.php create mode 100644 pacotes/linkedinoauth/tests/common.php create mode 100644 pacotes/openid/example-google.php create mode 100644 pacotes/openid/login.php create mode 100644 pacotes/openid/openid.php create mode 100644 pacotes/openid/provider/example-mysql.php create mode 100644 pacotes/openid/provider/example.php create mode 100644 pacotes/openid/provider/provider.php create mode 100644 pacotes/twitteroauth/DOCUMENTATION create mode 100644 pacotes/twitteroauth/LICENSE.txt create mode 100644 pacotes/twitteroauth/README.txt create mode 100644 pacotes/twitteroauth/callback.php create mode 100644 pacotes/twitteroauth/clearsessions.php create mode 100644 pacotes/twitteroauth/config.php create mode 100644 pacotes/twitteroauth/connect.php create mode 100644 pacotes/twitteroauth/html.inc create mode 100644 pacotes/twitteroauth/images/darker.png create mode 100644 pacotes/twitteroauth/images/lighter.png create mode 100644 pacotes/twitteroauth/index.php create mode 100644 pacotes/twitteroauth/redirect.php create mode 100644 pacotes/twitteroauth/test.php create mode 100644 pacotes/twitteroauth/twitteroauth/OAuth.php create mode 100644 pacotes/twitteroauth/twitteroauth/twitteroauth.php diff --git a/admin/admin.db b/admin/admin.db index 9d6c82a..8cb59ec 100644 Binary files a/admin/admin.db and b/admin/admin.db differ diff --git a/admin/index.html b/admin/index.html index 42c6d50..2bbce8e 100644 --- a/admin/index.html +++ b/admin/index.html @@ -181,6 +181,7 @@ essa criação podem ser obtidos no item "Outras opçes".

+ @@ -191,6 +192,8 @@ essa criação podem ser obtidos no item "Outras opçes".

+ +
Ajusta mapfiles
Estatísticas
Adiciona as tabelas necessrias verso 4.5 do i3Geo e que no existiam nas veses anteriores
Descrição do banco padrão (SQLITE)
Criar banco de dados
Ver xml com a lista de serviços WS (webservices convencionais)
Ver xml com a lista de sistemas que adicionam temas especiais
Ver RSS com os grupos, subgrupos e temas
Ver RSS com os comentrios sobre os temas
Ver XML para árvorehiperbólica
diff --git a/admin/js/editormapfile.js b/admin/js/editormapfile.js index 653b6a6..3bf9189 100644 --- a/admin/js/editormapfile.js +++ b/admin/js/editormapfile.js @@ -1123,6 +1123,8 @@ function montaEditorMetadados(dados) titulo:"Aplica extensao (APLICAEXTENSAO)",id:"",value:dados.aplicaextensao,tipo:"text",div:"
"}, {ajuda:"Indica se o usurio pode abrir o editor de SQL para poder alterar o elemento DATA do Mapfile.", titulo:"Permite editar SQL (EDITORSQL)",id:"",value:dados.editorsql,tipo:"text",div:"
"}, + {ajuda:"Indica se o usurio pode fazer comentrios no tema", + titulo:"Permite comentar (PERMITECOMENTARIO)",id:"",value:dados.permitecomentario,tipo:"text",div:"
"}, {ajuda:"Indica se o usurio pode fazer download do tema", titulo:"Download (DOWNLOAD)",id:"",value:dados.download,tipo:"text",div:"
"}, {ajuda:"Endereo de um arquivo para download dos dados (caminho completo no servidor). Se definido, o sistema ir usar esse arquivo ao invs de gerar os dados, quando o usurio clicar nas opes de download. Se no for definido, o arquivo de download gerado diretamente do original, convertendo do banco ou copiando o arquivo definido em DATA.", @@ -1203,6 +1205,10 @@ function montaEditorMetadados(dados) temp += core_combosimnao(dados.editorsql) temp += "" $i("cEditorsql").innerHTML = temp + temp = "" + $i("cPermitecomentario").innerHTML = temp temp = "" @@ -1563,7 +1569,7 @@ function salvarDadosEditor(tipo,codigoMap,codigoLayer,indiceClasse,indiceEstilo, else {alert("Valor de escala incorreto");return;} } - var campos = new Array("cache","iconetema","ltempoformatodata","ltempoiteminicio","ltempoitemfim","ltempoitemtitulo","ltempoitemdescricao","ltempoitemtip","ltempoitemimagem","ltempoitemicone","ltempoitemlink","editorsql","description_template","palletefile","palletestep","arquivodownload","aplicaextensao","classestamanho","classessimbolo","classescor","classesnome","classesitem","mensagem","identifica","extensao","escondido","download","escala","tema","classe","tip","itenslink","itens","itensdesc") + var campos = new Array("permitecomentario","cache","iconetema","ltempoformatodata","ltempoiteminicio","ltempoitemfim","ltempoitemtitulo","ltempoitemdescricao","ltempoitemtip","ltempoitemimagem","ltempoitemicone","ltempoitemlink","editorsql","description_template","palletefile","palletestep","arquivodownload","aplicaextensao","classestamanho","classessimbolo","classescor","classesnome","classesitem","mensagem","identifica","extensao","escondido","download","escala","tema","classe","tip","itenslink","itens","itensdesc") var par = "&codigoMap="+codigoMap+"&codigoLayer="+codigoLayer var prog = "../php/editormapfile.php?funcao=alterarMetadados" } diff --git a/admin/php/classe_arvore.php b/admin/php/classe_arvore.php index 0fa26d9..b06be4d 100644 --- a/admin/php/classe_arvore.php +++ b/admin/php/classe_arvore.php @@ -658,7 +658,6 @@ Verifica se uma string ocorre em um array $texto = mb_convert_encoding($texto,mb_detect_encoding($texto),"UTF-8"); else $texto = mb_convert_encoding($texto,mb_detect_encoding($texto),"ISO-8859-1"); - return $texto; } } diff --git a/admin/php/conexao.php b/admin/php/conexao.php index b357458..37bdffd 100644 --- a/admin/php/conexao.php +++ b/admin/php/conexao.php @@ -74,7 +74,7 @@ if($conexaoadmin == "") $arquivosqlite = $locaplic."/admin/admin.db"; if(!file_exists($arquivosqlite)) { - echo "O arquivo menutemas/admin.db no existe. Utilize i3geo/admin/criabanco.php para criar o banco de dados SQLITE."; + echo "O arquivo admin.db no existe. Utilize i3geo/admin/criabanco.php para criar o banco de dados SQLITE."; exit; } $conAdmin = "sqlite:$arquivosqlite"; diff --git a/admin/php/criabanco.php b/admin/php/criabanco.php index f88522b..66fec7a 100644 --- a/admin/php/criabanco.php +++ b/admin/php/criabanco.php @@ -5,7 +5,7 @@ Title: criabanco.php Cria um novo banco de dados de administrao. Se vc quiser recriar o banco de dados default, apague o arquivo -i3geo/menutemas/admin.db ou faa uma cpia. Depois s executar esse programa. +i3geo/admin/admin.db ou faa uma cpia. Depois s executar esse programa. Se a configurao do arquivo de conexo foi alterada (veja ms_configura.php), o novo banco ir ser criado conforme a nova string de conexo. @@ -60,15 +60,17 @@ $tabelas = array( "CREATE TABLE i3geoadmin_raiz (ordem NUMERIC, id_tema NUMERIC, id_menu NUMERIC, id_nivel NUMERIC, id_raiz INTEGER PRIMARY KEY, nivel NUMERIC, perfil TEXT)", "CREATE TABLE i3geoadmin_n1 (publicado TEXT, ordem NUMERIC, id_menu NUMERIC, id_grupo NUMERIC, id_n1 INTEGER PRIMARY KEY, n1_perfil TEXT)", "CREATE TABLE i3geoadmin_n2 (publicado TEXT, ordem NUMERIC, id_n1 NUMERIC, id_n2 INTEGER PRIMARY KEY, id_subgrupo NUMERIC, n2_perfil TEXT)", -"CREATE TABLE i3geoadmin_n3 (publicado TEXT, ordem NUMERIC, id_n2 NUMERIC, id_n3 INTEGER PRIMARY KEY, id_tema NUMERIC, n3_perfil TEXT)" +"CREATE TABLE i3geoadmin_n3 (publicado TEXT, ordem NUMERIC, id_n2 NUMERIC, id_n3 INTEGER PRIMARY KEY, id_tema NUMERIC, n3_perfil TEXT)", +"CREATE TABLE i3geoadmin_comentarios (comentario TEXT, data TEXT, openidnome TEXT, openidimagem TEXT, openidservico TEXT, openidusuario TEXT, openidurl TEXT, id_tema NUMERIC)" + ); if($conexaoadmin == "") { - if(file_exists("../../menutemas/admin.db")) - {echo "Arquivo menutemas/admin.db ja existe";exit;} - $banco = sqlite_open("../../menutemas/admin.db",0666); + if(file_exists("../../admin/admin.db")) + {echo "Arquivo admin/admin.db ja existe";exit;} + $banco = sqlite_open("../../admin/admin.db",0666); $banco = null; - $dbhw = new PDO('sqlite:../../menutemas/admin.db'); + $dbhw = new PDO('sqlite:../../admin/admin.db'); } else { diff --git a/admin/php/editormapfile.php b/admin/php/editormapfile.php index d734f65..6d3feee 100644 --- a/admin/php/editormapfile.php +++ b/admin/php/editormapfile.php @@ -692,6 +692,8 @@ switch (strtoupper($funcao)) cache + permitecomentario + Retorno: {JSON} @@ -1331,11 +1333,12 @@ function pegaMetadados() $dados["ltempoitemicone"] = $layer->getmetadata("ltempoitemicone"); $dados["ltempoitemlink"] = $layer->getmetadata("ltempoitemlink"); $dados["iconetema"] = $layer->getmetadata("iconetema"); + $dados["permitecomentario"] = $layer->getmetadata("permitecomentario"); return $dados; } function alterarMetadados() { - global $iconetema,$ltempoformatodata,$ltempoiteminicio,$ltempoitemfim,$ltempoitemtitulo,$ltempoitemdescricao,$ltempoitemtip,$ltempoitemimagem,$ltempoitemicone,$ltempoitemlink,$description_template,$palletestep,$palletefile,$arquivodownload,$codigoMap,$codigoLayer,$locaplic,$aplicaextensao,$classestamanho,$classessimbolo,$classescor,$classesnome,$classesitem,$mensagem,$identifica,$extensao,$escondido,$download,$escala,$tema,$classe,$tip,$itenslink,$itens,$itensdesc,$editorsql,$cache; + global $permitecomentario,$iconetema,$ltempoformatodata,$ltempoiteminicio,$ltempoitemfim,$ltempoitemtitulo,$ltempoitemdescricao,$ltempoitemtip,$ltempoitemimagem,$ltempoitemicone,$ltempoitemlink,$description_template,$palletestep,$palletefile,$arquivodownload,$codigoMap,$codigoLayer,$locaplic,$aplicaextensao,$classestamanho,$classessimbolo,$classescor,$classesnome,$classesitem,$mensagem,$identifica,$extensao,$escondido,$download,$escala,$tema,$classe,$tip,$itenslink,$itens,$itensdesc,$editorsql,$cache; $dados = array(); $mapfile = $locaplic."/temas/".$codigoMap.".map"; $mapa = ms_newMapObj($mapfile); @@ -1375,6 +1378,7 @@ function alterarMetadados() $layer->setmetadata("ltempoitemicone",$ltempoitemicone); $layer->setmetadata("ltempoitemlink",$ltempoitemlink); $layer->setmetadata("iconetema",$iconetema); + $layer->setmetadata("permitecomentario",$permitecomentario); $mapa->save($mapfile); removeCabecalho($mapfile); return "ok"; diff --git a/admin/php/sqlite.php b/admin/php/sqlite.php index afffe2f..826636d 100644 --- a/admin/php/sqlite.php +++ b/admin/php/sqlite.php @@ -32,13 +32,13 @@ Arquivo: i3geo/admin/php/sqlite.php */ -if(!file_exists("../../menutemas/admin.db")) +if(!file_exists("../admin.db")) { echo "O arquivo menutemas/admin.db no existe. Utilize i3geo/admin/criasqlite.php para criar o banco de dados SQLITE."; exit; } echo "
";
-$dbh = new PDO('sqlite:../../menutemas/admin.db');
+$dbh = new PDO('sqlite:../admin.db');
 echo "

Lista de tabelas

"; $q = $dbh->query("SELECT name FROM (SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type='table' ORDER BY name",PDO::FETCH_ASSOC); $resultado = $q->fetchAll(); diff --git a/admin/php/upgradebanco44_45.php b/admin/php/upgradebanco44_45.php new file mode 100644 index 0000000..761bc37 --- /dev/null +++ b/admin/php/upgradebanco44_45.php @@ -0,0 +1,68 @@ +getAttribute(PDO::ATTR_DRIVER_NAME) == "pgsql") + { + $tabela = str_replace("INTEGER PRIMARY KEY","SERIAL PRIMARY KEY NOT NULL",$tabela); + } + $q = $dbhw->query($tabela); +} +$banco = null; +echo "Feito!!!"; +?> \ No newline at end of file diff --git a/admin/php/xml.php b/admin/php/xml.php index 59e3571..e6bb3fb 100644 --- a/admin/php/xml.php +++ b/admin/php/xml.php @@ -92,6 +92,28 @@ function geraXmlSistemas($perfil,$locaplic,$editores) return $xml; } /* +Function: geraRSScomentariosTemas + +RSS com os comentarios sobre um ou todos os temas + +Parametros: + +locaplic {string} - localizao do i3Geo no sistema de arquivos + +id_tema {numeric} - (opcional) id do tema para mostrar apenas os comentrios de um tema + +Retorno: + +RSS +*/ +function geraRSScomentariosTemas($locaplic,$id_tema="") +{ + $sql = "select b.nome_tema||' '||a.data as nome_ws,a.openidnome||' '||a.openidurl||' <br>'||a.comentario as desc_ws, a.openidnome as autor_ws, b.link_tema as link_ws from i3geoadmin_comentarios as a,i3geoadmin_temas as b where a.id_tema = b.id_tema "; + if($id_tema != "") + {$sql .= " and a.id_tema = $id_tema ";} + return geraXmlRSS($locaplic,$sql,"Lista de comentarios"); +} +/* Function: geraRSStemas RSS com os temas cadastrados diff --git a/admin/rsscomentariostemas.php b/admin/rsscomentariostemas.php new file mode 100644 index 0000000..09cb93c --- /dev/null +++ b/admin/rsscomentariostemas.php @@ -0,0 +1,66 @@ + + +Parametros: + +id_tema {numeric} - (opcional) id do tema para mostrar apenas os comentrios de um tema + +Licenca: + +GPL2 + +i3Geo Interface Integrada de Ferramentas de Geoprocessamento para Internet + +Direitos Autorais Reservados (c) 2006 Ministrio do Meio Ambiente Brasil +Desenvolvedor: Edmar Moretti edmar.moretti@mma.gov.br + +Este programa software livre; voc pode redistribu-lo +e/ou modific-lo sob os termos da Licena Pblica Geral +GNU conforme publicada pela Free Software Foundation; + +Este programa distribudo na expectativa de que seja til, +porm, SEM NENHUMA GARANTIA; nem mesmo a garantia implcita +de COMERCIABILIDADE OU ADEQUAO A UMA FINALIDADE ESPECFICA. +Consulte a Licena Pblica Geral do GNU para mais detalhes. +Voc deve ter recebido uma cpia da Licena Pblica Geral do +GNU junto com este programa; se no, escreva para a +Free Software Foundation, Inc., no endereo +59 Temple Street, Suite 330, Boston, MA 02111-1307 USA. + +Arquivo: + +i3geo/admin/rsscomentariostemas.php +*/ + +error_reporting(0); +if(!isset($locaplic)) +{ + $locaplic = ""; + if(file_exists("../../../ms_configura.php")) + {include_once("../../../ms_configura.php");} + else + { + if(file_exists("../../ms_configura.php")) + {include_once("../../ms_configura.php");} + else + { + if(file_exists("../ms_configura.php")) + {include_once("../ms_configura.php");} + else + include_once("ms_configura.php"); + } + } +} +include_once($locaplic."/classesphp/pega_variaveis.php"); +include_once($locaplic."/admin/php/xml.php"); +$parametros = array_merge($_POST,$_GET); +if(empty($parametros["id_tema"])) +{$parametros["id_tema"] = "";} +echo header("Content-type: application/xml"); +echo geraRSScomentariosTemas($locaplic,$parametros["id_tema"]); +?> diff --git a/admin/rsstemas.php b/admin/rsstemas.php index ef95080..41d1416 100644 --- a/admin/rsstemas.php +++ b/admin/rsstemas.php @@ -38,7 +38,6 @@ Arquivo: i3geo/admin/rsstemas.php */ - error_reporting(0); if(!isset($locaplic)) { diff --git a/classesjs/classe_arvoredecamadas.js b/classesjs/classe_arvoredecamadas.js index 03af1e6..4629923 100644 --- a/classesjs/classe_arvoredecamadas.js +++ b/classesjs/classe_arvoredecamadas.js @@ -246,8 +246,7 @@ i3GEO.arvoreDeCamadas = { "editorsql":"sim", - "iconetema":"" - + "iconetema":"" } ] @@ -779,6 +778,9 @@ i3GEO.arvoreDeCamadas = { //i3GEO.arvoreDeCamadas.adicionaOpcaoTema($trad("t43"),$trad("t43"),'i3GEO.tema.dialogo.aplicarsld(\"'+ltema.name+'\")',node); if(ltema.editorsql == "sim" || ltema.editorsql == "SIM") {i3GEO.arvoreDeCamadas.adicionaOpcaoTema($trad("t40"),$trad("t41"),'i3GEO.tema.dialogo.editorsql(\"'+ltema.name+'\")',node);} + if(ltema.permitecomentario.toLowerCase() !== "nao") + {i3GEO.arvoreDeCamadas.adicionaOpcaoTema($trad("t45"),$trad("t45"),'i3GEO.tema.dialogo.comentario(\"'+ltema.name+'\")',node);} + if(i3GEO.arvoreDeTemas.OPCOESADICIONAIS.navegacaoDir == true) {i3GEO.arvoreDeCamadas.adicionaOpcaoTema($trad("t44"),""+$trad("t44")+"",'i3GEO.tema.dialogo.salvaMapfile(\"'+ltema.name+'\")',node);} node.loadComplete(); diff --git a/classesjs/classe_arvoredetemas.js b/classesjs/classe_arvoredetemas.js index ea8f1c5..01239b0 100644 --- a/classesjs/classe_arvoredetemas.js +++ b/classesjs/classe_arvoredetemas.js @@ -83,7 +83,9 @@ i3GEO.arvoreDeTemas = { carousel: true, - uploadgpx: true + uploadgpx: true, + + comentarios: true } Tipo: @@ -108,7 +110,8 @@ i3GEO.arvoreDeTemas = { estrelas: true, refresh: true, carousel: true, - uploadgpx: true + uploadgpx: true, + comentarios: true }, /* Propriedade: FATORESTRELA @@ -976,7 +979,8 @@ i3GEO.arvoreDeTemas = { idtema:raiz[i].tid, fonte:raiz[i].link, ogc:raiz[i].ogc, - kmz:raiz[i].kmz + kmz:raiz[i].kmz, + permitecomentario:raiz[i].permitecomentario }, node, false, @@ -1209,6 +1213,17 @@ i3GEO.arvoreDeTemas = { tempNode.enableHighlight = false; tempNode.isLeaf = true; } + if (node.data.permitecomentario != "nao" && i3GEO.arvoreDeTemas.OPCOESADICIONAIS.comentarios === true){ + html = "Comentrio"; + tempNode = new YAHOO.widget.HTMLNode( + {html:html}, + node, + false, + true + ); + tempNode.enableHighlight = false; + tempNode.isLeaf = true; + } if(i3GEO.arvoreDeTemas.OPCOESADICIONAIS.qrcode === true){ lkgrcode = i3GEO.arvoreDeTemas.LOCAPLIC+"/pacotes/qrcode/php/qr_html.php?d="+i3GEO.arvoreDeTemas.LOCAPLIC+"/mobile/index.php?temasa="+node.data.idtema; lkgrcode1 = i3GEO.arvoreDeTemas.LOCAPLIC+"/pacotes/qrcode/php/qr_img.php?d="+i3GEO.arvoreDeTemas.LOCAPLIC+"/mobile/index.php?temasa="+node.data.idtema; diff --git a/classesjs/classe_barradebotoes.js b/classesjs/classe_barradebotoes.js index 06fbea6..bfac776 100644 --- a/classesjs/classe_barradebotoes.js +++ b/classesjs/classe_barradebotoes.js @@ -510,6 +510,8 @@ i3GEO.barraDeBotoes = { */ inicializaBarra:function(idconteudo,idconteudonovo,barraZoom,x,y,onde){ if(typeof(console) !== 'undefined'){console.info("i3GEO.barraDeBotoes.inicializaBarra()");} + if(i3GEO.util.pegaCookie("botoesAjuda") == "nao") + {i3GEO.barraDeBotoes.AJUDA = false;} if(i3GEO.barraDeBotoes.TEMPLATEBOTAO === "") {i3GEO.barraDeBotoes.TEMPLATEBOTAO = "

 

";} var tipo,mostra,numerobotoes = 0,i,temp,elementos,nelementos = 0,e,wj,recuo,novoel,alturadisponivel,n,chaves,re,estilo; @@ -908,10 +910,9 @@ i3GEO.barraDeBotoes = { else {document.body.appendChild(divmensagem);} if(i3GEO.barraDeBotoes.TIPOAJUDA == "horizontal") - {divmensagem.innerHTML = "
fecha
";} + {divmensagem.innerHTML = "
fecha
";} if(i3GEO.barraDeBotoes.TIPOAJUDA == "vertical") - {divmensagem.innerHTML = "
fecha
";} - + {divmensagem.innerHTML = "
fecha
";} } if(mensagem != ""){ if(i3GEO.barraDeBotoes.TIPOAJUDA == "horizontal"){ diff --git a/classesjs/classe_i3geo.js b/classesjs/classe_i3geo.js index 69a0559..965b7e9 100644 --- a/classesjs/classe_i3geo.js +++ b/classesjs/classe_i3geo.js @@ -114,6 +114,8 @@ i3GEO = { embedLegenda {String} - sim|nao indica se na inicializao a legenda foi inserida no contedo do mapa ou no celularef {Numeric} - tamanho da clula do mapa de referncia + + autenticadoopenid {sim|nao} - indica se o usurio foi autenticado em alguma rede social */ parametros: { mapexten: "", @@ -141,7 +143,8 @@ i3GEO = { mensageminicia:"", interfacePadrao:"geral.htm", embedLegenda:"nao", - celularef:"" + celularef:"", + autenticadoopenid:"nao" }, /* Propriedade: finaliza @@ -224,37 +227,6 @@ i3GEO = { // tamanho = i3GEO.calculaTamanho(); i3GEO.Interface.cria(tamanho[0],tamanho[1]); - - /* - i3GEO.parametros = { - mapexten: "", - mapscale: "", - mapres: "", - pixelsize: "", - mapfile: "", - cgi: "", - extentTotal: "", - mapimagem: "", - geoip: "", - listavisual: "", - utilizacgi:"", - versaoms:"", - versaomscompleta:"", - mensagens:"", - w: tamanho[0], - h: tamanho[1], - locsistemas:"", - locidentifica:"", - r:"", - locmapas:"", - extentref:"", - kmlurl:"", - mensageminicia:"", - interfacePadrao:"geral.htm", - embedLegenda:"nao", - celularef: "" - }; - */ if(tamanho[0] < 550){ i = $i(i3GEO.gadgets.PARAMETROS.mostraQuadros.idhtml); if(i){i.style.display = "none";} @@ -295,57 +267,12 @@ i3GEO = { } else{ if(retorno.data.variaveis){ - // - //executa com eval a string que retornada pelo servidor (funo inicia do mapa_controle.php - // - - /* - tempo = ""; - titulo = ""; - eval(retorno.data.variaveis); - try{ - if (titulo !== "") - {top.document.title = titulo;} - } - catch(e){} - i3GEO.ajuda.mostraJanela("Tempo de desenho em segundos: "+tempo,""); - - try{ - i3GEO.parametros.mapexten= mapexten; - i3GEO.parametros.mapscale= parseInt(mapscale,10); - i3GEO.parametros.mapres= mapres; - i3GEO.parametros.pixelsize= g_celula; - i3GEO.parametros.mapfile= mapfile; - i3GEO.parametros.cgi= cgi; - i3GEO.parametros.extentTotal=mapexten; - i3GEO.parametros.mapimagem= mapimagem; - i3GEO.parametros.geoip= geoip; - i3GEO.parametros.listavisual= listavisual; - i3GEO.parametros.utilizacgi= utilizacgi; - i3GEO.parametros.versaoms= versaoms; - i3GEO.parametros.mensagens= mensagens; - i3GEO.parametros.locsistemas = locsistemas; - i3GEO.parametros.locidentifica = locidentifica; - i3GEO.parametros.r = r; - i3GEO.parametros.locmapas = locmapas; - i3GEO.parametros.extentref = extentref; - i3GEO.parametros.versaoms = versaoms; - i3GEO.parametros.versaomscompleta = versaomscompleta; - i3GEO.parametros.kmlurl = kmlurl; - i3GEO.parametros.mensageminicia = mensagemInicia; - i3GEO.parametros.interfacePadrao = interfacePadrao; - i3GEO.parametros.embedLegenda = embedLegenda; - } - catch(e){alert("Erro durante a definicao de i3GEO.parametros "+e);} - */ i3GEO.parametros = retorno.data.variaveis; - i3GEO.parametros.mapscale = i3GEO.parametros.mapscale*1; i3GEO.parametros.mapres = i3GEO.parametros.mapres*1; i3GEO.parametros.pixelsize = i3GEO.parametros.pixelsize*1; i3GEO.parametros.w = i3GEO.parametros.w*1; i3GEO.parametros.h = i3GEO.parametros.h*1; - i3GEO.arvoreDeCamadas.CAMADAS = retorno.data.temas; if(retorno.data.variaveis.navegacaoDir == "sim") {i3GEO.arvoreDeTemas.OPCOESADICIONAIS.navegacaoDir = true;} @@ -389,8 +316,6 @@ i3GEO = { if (!$i("i3geo")) {document.body.id = "i3geo";} $i("i3geo").className = "yui-skin-sam"; - //if($i("mst")) - //{$i("mst").style.visibility ="hidden";} // //se i3GEO.configura.sid = "", o html foi aberto diretamente //ento, necessrio criar os arquivos temporrios do mapa diff --git a/classesjs/classe_tema.js b/classesjs/classe_tema.js index 17bd4ab..10fbbe1 100644 --- a/classesjs/classe_tema.js +++ b/classesjs/classe_tema.js @@ -350,6 +350,18 @@ i3GEO.tema = { */ dialogo:{ /* + Function: comentario + + Abre a janela de dilogo para o usurio ver e inserir comentarios em um tema + + Parametros: + + tema - cdigo do tema escolhido + */ + comentario: function(tema){ + i3GEO.janela.cria("530px","330px",i3GEO.configura.locaplic+"/ferramentas/comentarios/index.php?tema="+tema+"&g_sid="+i3GEO.configura.sid+"&locaplic="+i3GEO.configura.locaplic,"",""," Comentrios de "+tema+"    ","comentario"+Math.random()); + }, + /* Function: cortina Abre a janela de dilogo da ferramenta cortina diff --git a/classesjs/dicionario.js b/classesjs/dicionario.js index 5194a54..c76c009 100644 --- a/classesjs/dicionario.js +++ b/classesjs/dicionario.js @@ -761,6 +761,13 @@ en:"Save mapfile", es:"Guardar mapfile", it:"Salva mapfile" }], +"t45": [ +{ +pt: "Comentar", +en:"Comentar", +es:"Comentar", +it:"Comentar" +}], //guia adiciona "a1":[ { diff --git a/classesjs/dicionario_ajuda.js b/classesjs/dicionario_ajuda.js index 4caa768..e4fa5e0 100644 --- a/classesjs/dicionario_ajuda.js +++ b/classesjs/dicionario_ajuda.js @@ -786,6 +786,14 @@ g_traducao_ajuda = { pt:"Salva as definies da camada no arquivo mapfile de origem", complemento:"Essa opo s ativada para usurios que so administradores. Permite que a camada seja alterada, por exemplo, modificando-se a legenda, e que o resultado seja salvo nas definies originais da camada.", apijs:"i3GEO.tema.dialogo.salvaMapfile()" + }, + "93": { + titulo: "Comentrios", + diretorio:"i3geo/ferramentas/comentarios", + categoria:"5", + pt:"Mostra os comentrios existentes sobre o tema e permite ao usurio inserir novos", + complemento:"Para entar com um comentrio, o usurio precisa ser autenticado em alguma das redes sociais compatveis com a rotina de login disponvel no i3Geo", + apijs:"i3GEO.tema.dialogo.comentario()" } } }; diff --git a/classesphp/classe_mapa.php b/classesphp/classe_mapa.php index 435bec8..d822f7a 100644 --- a/classesphp/classe_mapa.php +++ b/classesphp/classe_mapa.php @@ -221,6 +221,9 @@ string - javascript com os parametros $ltempo = "nao"; if($oLayer->getmetadata("ltempoformatodata") !== "") {$ltempo = "sim";} + $permitecomentario = "nao"; + if($oLayer->getmetadata("nomeoriginal") != "" && strtoupper($oLayer->getmetadata("pemitecomentario")) != "NAO") + {$permitecomentario = "sim";} $temas[] = array( "name"=>($oLayer->name), "status"=>($oLayer->status), @@ -240,7 +243,8 @@ string - javascript com os parametros "linhadotempo"=>$ltempo, "escondido"=>strtolower($escondido), "iconetema"=>($oLayer->getmetadata("iconetema")), - "classe"=>($oLayer->getmetadata("classe")) + "classe"=>($oLayer->getmetadata("classe")), + "permitecomentario"=>$permitecomentario ); } } diff --git a/classesphp/mapa_controle.php b/classesphp/mapa_controle.php index 7497f3f..75ed2e1 100644 --- a/classesphp/mapa_controle.php +++ b/classesphp/mapa_controle.php @@ -124,11 +124,11 @@ if ($funcao != "criaMapa") eval("\$".$k."='".$_SESSION[$k]."';"); } $postgis_mapa = $_SESSION["postgis_mapa"]; - if(isset($fingerprint)) - { + //if(isset($fingerprint)) + //{ if (md5('I3GEOSEC' . $_SERVER['HTTP_USER_AGENT'] . session_id()) != $fingerprint) {exit;} - } + //} } // //verifica se deve ativar o debug @@ -2929,7 +2929,7 @@ function redesenhaMapa() $m->salva(); } include_once("classe_mapa.php"); - $m = New Mapa($map_file); + $m = New Mapa($map_file,$locaplic); $par = $m->parametrosTemas(); // //na interface googlemaps no necessrio gerar a imagem diff --git a/classesphp/mapa_inicia.php b/classesphp/mapa_inicia.php index 7bf2717..32c056d 100644 --- a/classesphp/mapa_inicia.php +++ b/classesphp/mapa_inicia.php @@ -42,6 +42,8 @@ Inicia um mapa e obtm os parmetros necessrios para o funcionamento da interfa Globais: +$openid - indica se o usurio foi ou no autenticado em alguma rede social (veja i3geo/pacotes/openid) + $interfacePadrao - interface definida em ms_configura.php $navegadoresLocais - array que indica quais usurios podem navegar no servidor @@ -96,7 +98,7 @@ Retorno: */ function iniciaMapa() { - global $interfacePadrao,$mensagemInicia,$kmlurl,$tituloInstituicao,$tempo,$navegadoresLocais,$locaplic,$embedLegenda,$map_file,$mapext,$w,$h,$R_path,$locmapserv,$utilizacgi,$expoeMapfile,$interface; + global $openid,$interfacePadrao,$mensagemInicia,$kmlurl,$tituloInstituicao,$tempo,$navegadoresLocais,$locaplic,$embedLegenda,$map_file,$mapext,$w,$h,$R_path,$locmapserv,$utilizacgi,$expoeMapfile,$interface; if(!isset($kmlurl)) {$kmlurl = "";} error_reporting(E_ALL); @@ -195,7 +197,7 @@ function iniciaMapa() // $qyfile = str_replace(".map",".qy",$map_file); $arqsel = (file_exists($qyfile)) ? true : false; - $m = New Mapa($map_file); + $m = New Mapa($map_file,$locaplic); $temas = $m->parametrosTemas(); //$m->ligaDesligaTemas("",implode(",",$m->nomes),"nao"); // @@ -264,6 +266,10 @@ function iniciaMapa() $res["mappath"] = $imgo->imagepath; $res["mapurl"] = $imgo->imageurl; $res["navegacaoDir"] = $navegadoresLocais; + if($openid == true) + {$res["autenticadoopenid"] = "sim";} + else + {$res["autenticadoopenid"] = "nao";} copy($map_file,(str_replace(".map","reinc.map",$map_file))); copy($map_file,(str_replace(".map","seguranca.map",$map_file))); diff --git a/ferramentas/comentarios/index.php b/ferramentas/comentarios/index.php new file mode 100644 index 0000000..68c86d2 --- /dev/null +++ b/ferramentas/comentarios/index.php @@ -0,0 +1,112 @@ + + + + + + +Inserir comentrio"; +} +function formularioInsere() +{ + echo "

Adicione um comentrio:

"; + $url = $_SESSION["locaplic"]."/ferramentas/comentarios/index.php?g_sid=".$_SESSION["g_sid"]."&tema=".$_SESSION["tema"]; + echo "
"; + echo "
"; + echo " "; + echo "
"; + echo "

Para alterar o seu login e escolher uma outra rede, clique aqui"; +} +function listaComentarios() +{ + $locaplic = "../.."; + include("../../admin/php/conexao.php"); + $data = gmdate("d-m-Y\TH:i:s\Z"); + $id_tema = $dbh->query("select * from i3geoadmin_temas where codigo_tema = '".$_SESSION["tema"]."' ",PDO::FETCH_ASSOC); + $id_tema = $id_tema->fetchAll(); + $id_tema = $id_tema[0]["id_tema"]; + $lista = $dbh->query("select * from i3geoadmin_comentarios where id_tema = $id_tema ",PDO::FETCH_ASSOC); + $lista = $lista->fetchAll(); + echo "

todos os comentrios"; + echo " comentrios para o tema

"; + + echo ""; + foreach ($lista as $reg) + { + //echo ""; + echo ""; + echo ""; + echo ""; + } + echo "
 
"; + if($reg["openidimagem"] != "") + {echo " ";} + echo "

".$reg["openidnome"]."

".$reg["data"]."
".mb_convert_encoding($reg["comentario"],"ISO-8859-1",mb_detect_encoding($reg["comentario"]))."


"; + $dbhw = null; + $dbh = null; +} +function gravaComentario() +{ + //necessrio para os includes do admin.php + include_once("../../admin/php/conexao.php"); + $data = gmdate("d-m-Y\TH:i:s\Z"); + $id_tema = $dbh->query("select * from i3geoadmin_temas where codigo_tema = '".$_SESSION["tema"]."' ",PDO::FETCH_ASSOC); + $id_tema = $id_tema->fetchAll(); + $id_tema = $id_tema[0]["id_tema"]; + $q = "INSERT INTO i3geoadmin_comentarios (comentario,data,openidnome,openidimagem,openidservico,openidusuario,openidurl,id_tema) VALUES ('".converte($_POST["novocomentario"])."','".$data."','".$_SESSION["openidnome"]."','".$_SESSION["openidimagem"]."','".$_SESSION["openidservico"]."','".$_SESSION["openidusuario"]."','".$_SESSION["openidurl"]."','".$id_tema."')"; + $dbhw->query($q); + $dbhw = null; + $dbh = null; +} +function converte($texto){ + global $convUTF; + if($convUTF == true) + $texto = mb_convert_encoding($texto,mb_detect_encoding($texto),"UTF-8"); + else + $texto = mb_convert_encoding($texto,mb_detect_encoding($texto),"ISO-8859-1"); + return $texto; +} +?> + \ No newline at end of file diff --git a/guia_de_migracao.txt b/guia_de_migracao.txt index 414d219..78ba804 100644 --- a/guia_de_migracao.txt +++ b/guia_de_migracao.txt @@ -18,7 +18,13 @@ Para a verso 4.5 A pasta "images" foi removida e as imagens movidas para a pasta "imagens\depreciado" - + Opo de comentrios em temas + Foram acrescentadas novas variveis em ms_configura.php. Veja esse arquivo para editar as variveis e registrar + as APIs das redes sociais como Twitter e Facebook + Por default, todos os temas podem receber comentrios. Para bloquear comentrios em temas especficos, + utilize o editor de mapfiles do sistema de admnistrao + Os comentrios so armazenados em uma tabela no banco de dados de administrao. Essa tabela precisa ser criada no banco. + Para criar a tabela veja o item "Outras opes" em http://localhost/i3geo/admin ------------------------------------------------------------------------------------------------- Para a verso 4.4 diff --git a/imagens/redes_blogger.png b/imagens/redes_blogger.png new file mode 100644 index 0000000..9d95271 Binary files /dev/null and b/imagens/redes_blogger.png differ diff --git a/imagens/redes_facebook.png b/imagens/redes_facebook.png new file mode 100644 index 0000000..4084266 Binary files /dev/null and b/imagens/redes_facebook.png differ diff --git a/imagens/redes_google.png b/imagens/redes_google.png new file mode 100644 index 0000000..9a68d75 Binary files /dev/null and b/imagens/redes_google.png differ diff --git a/imagens/redes_linkedin.png b/imagens/redes_linkedin.png new file mode 100644 index 0000000..75ae505 Binary files /dev/null and b/imagens/redes_linkedin.png differ diff --git a/imagens/redes_myspace.png b/imagens/redes_myspace.png new file mode 100644 index 0000000..995749e Binary files /dev/null and b/imagens/redes_myspace.png differ diff --git a/imagens/redes_oauth.png b/imagens/redes_oauth.png new file mode 100644 index 0000000..dba375d Binary files /dev/null and b/imagens/redes_oauth.png differ diff --git a/imagens/redes_openid.png b/imagens/redes_openid.png new file mode 100644 index 0000000..8a8a924 Binary files /dev/null and b/imagens/redes_openid.png differ diff --git a/imagens/redes_twitter.png b/imagens/redes_twitter.png new file mode 100644 index 0000000..a38be33 Binary files /dev/null and b/imagens/redes_twitter.png differ diff --git a/imagens/redes_windowslive.png b/imagens/redes_windowslive.png new file mode 100644 index 0000000..606a9bd Binary files /dev/null and b/imagens/redes_windowslive.png differ diff --git a/imagens/redes_wordpress.png b/imagens/redes_wordpress.png new file mode 100644 index 0000000..a634c44 Binary files /dev/null and b/imagens/redes_wordpress.png differ diff --git a/interface/googlemaps.phtml b/interface/googlemaps.phtml index 396b910..40822a6 100644 --- a/interface/googlemaps.phtml +++ b/interface/googlemaps.phtml @@ -141,6 +141,8 @@ i3GEO.idioma.IDSELETOR = "seletorIdiomas"; i3GEO.Interface.ATIVAMENUCONTEXTO = true; i3GEO.arvoreDeTemas.TIPOBOTAO = "radio"; i3GEO.arvoreDeTemas.ATIVATEMAIMEDIATO = true; +//para evitar a entrada de comentrios na rvore de camadas, modifique a opo de cada tema individualmente no sistema de administrao +i3GEO.arvoreDeTemas.OPCOESADICIONAIS.comentario = true; i3GEO.inicia(); diff --git a/ms_configura.php b/ms_configura.php index 7a94823..78e0188 100644 --- a/ms_configura.php +++ b/ms_configura.php @@ -43,6 +43,96 @@ Arquivo: ms_configura.php */ /* + Variavel: linkedinoauth (ainda no implementado) + + Parmetros registrados no Linkedin para permitir que o i3Geo faa autenticao com base na conta do usurio + + O Linkedin exige que cada site seja registrado para permitir que a API de autenticao funcione + + Veja o site para maiores informaes: http://developer.linkedin.com/docs/DOC-1008 + + Caso vc no queira permitir essa opo, deixe essa varivel vazia, e.x + + Ao registrar utilize o valor http://meuservidor/i3geo/pacotes/openid/login.php?login + + Exemplo: + + $linkedinoauth = array( + "consumerkey" => "0oQ30ge-ggKarx4HGaXVK118n8mekMBbFYTrC-agGV9hvxUXfeWwS1q7ZMvD-8LL", + "consumersecret" => "nRGXfHp1XNMt0eCG7tWJpoCcXX1uoZseDtgiU-CRy1ajqipo4KpjjZdDUXmqZGQA" + ); + + Tipo: + {array} +*/ +$linkedinoauth = ""; +/* + Variavel: facebookoauth + + Parmetros registrados no Facebook para permitir que o i3Geo faa autenticao com base na conta do usurio + + O Facebook exige que cada site seja registrado para permitir que a API de autenticao funcione + + Veja o site para maiores informaes: http://developers.facebook.com/setup/ + + Caso vc no queira permitir essa opo, deixe essa varivel vazia, e.x + + Ao registrar utilize o valor http://meuservidor/i3geo/pacotes/openid/login.php?login + + Exemplo: + + $facebookoauth = array( + "consumerkey" => "136279263094148", + "consumersecret" => "679fc4a007b1d289377fa8af8f7086b6" + ); + + Tipo: + {array} +*/ +$facebookoauth = array( + "consumerkey" => "136279263094148", + "consumersecret" => "679fc4a007b1d289377fa8af8f7086b6" + ); +/* + Variavel: twitteroauth + + Parmetros registrados no Twitter para permitir que o i3Geo faa autenticao com base na conta do usurio + + O Twitter exige que cada site seja registrado para permitir que a API de autenticao funcione + + Veja o site para maiores informaes: http://www.snipe.net/2009/07/writing-your-first-twitter-application-with-oauth/ + + Lista de aplicaes cadastradas: https://twitter.com/oauth_clients/ + + Caso vc no queira permitir essa opo, deixe essa varivel vazia, e.x + + $twitteroauth = ""; + + Ao registrar a aplicao, utilize o endereo do i3geo em Application Website, por exemplo http://meuservidor/i3geo + + Ao registrar utilize como "Callback URL" o valor http://meuservidor/i3geo/pacotes/openid/login.php?login + + Exemplo: + + $twitteroauth = array( + "consumerkey" => "vUvBcsOULjS0ewxuSvbS6w", + "consumersecret" => "0Hj6uCyycDCeNOgzTUF1bBSel75KtfbnCS4bxWVqaxk", + "requesttokenurl" => "https://twitter.com/oauth/request_token", + "accesstokenurl" => "https://twitter.com/oauth/access_token", + "authorizeurl" => "https://twitter.com/oauth/authorize" + ); + + Tipo: + {array} +*/ +$twitteroauth = array( + "consumerkey" => "vUvBcsOULjS0ewxuSvbS6w", + "consumersecret" => "0Hj6uCyycDCeNOgzTUF1bBSel75KtfbnCS4bxWVqaxk", + "requesttokenurl" => "https://twitter.com/oauth/request_token", + "accesstokenurl" => "https://twitter.com/oauth/access_token", + "authorizeurl" => "https://twitter.com/oauth/authorize" + ); +/* Variavel: mensagemInicia Mensagem de inicializao mostrada pelo programa ms_criamapa.php diff --git a/pacotes/facebookoauth/callback.php b/pacotes/facebookoauth/callback.php new file mode 100644 index 0000000..5b64158 --- /dev/null +++ b/pacotes/facebookoauth/callback.php @@ -0,0 +1,19 @@ + diff --git a/pacotes/facebookoauth/clearsessions.php b/pacotes/facebookoauth/clearsessions.php new file mode 100644 index 0000000..cef4815 --- /dev/null +++ b/pacotes/facebookoauth/clearsessions.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/pacotes/facebookoauth/config.php b/pacotes/facebookoauth/config.php new file mode 100644 index 0000000..cf9fad1 --- /dev/null +++ b/pacotes/facebookoauth/config.php @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/pacotes/facebookoauth/index.php b/pacotes/facebookoauth/index.php new file mode 100644 index 0000000..65fbbac --- /dev/null +++ b/pacotes/facebookoauth/index.php @@ -0,0 +1,28 @@ + + +
+ + + + + \ No newline at end of file diff --git a/pacotes/linkedinoauth/CHANGELOG.txt b/pacotes/linkedinoauth/CHANGELOG.txt new file mode 100644 index 0000000..b12ff1c --- /dev/null +++ b/pacotes/linkedinoauth/CHANGELOG.txt @@ -0,0 +1,15 @@ +== 2008.08.04 == +* Added LICENSE.txt file with MIT license, copyright owner is perhaps + dubious however. +== 2008.07.22 == +* Change to encoding to fix last change to encoding of spaces +== 2008.07.15 == +* Another change to encoding per + http://groups.google.com/group/oauth/browse_thread/thread/d39931d39b4af4bd +* A change to port handling to better deal with https and the like per + http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226 +* Fixed a small bug per + http://code.google.com/p/oauth/issues/detail?id=26 +* Added missing base_string debug info when using RSA-SHA1 +* Increased size of example endpoint input field and added note about + query strings diff --git a/pacotes/linkedinoauth/LICENSE.txt b/pacotes/linkedinoauth/LICENSE.txt new file mode 100644 index 0000000..89f0591 --- /dev/null +++ b/pacotes/linkedinoauth/LICENSE.txt @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2007 Andy Smith + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/pacotes/linkedinoauth/OAuth.php b/pacotes/linkedinoauth/OAuth.php new file mode 100644 index 0000000..3fe1864 --- /dev/null +++ b/pacotes/linkedinoauth/OAuth.php @@ -0,0 +1,866 @@ +key = $key; + $this->secret = $secret; + $this->callback_url = $callback_url; + } + + function __toString() { + return "OAuthConsumer[key=$this->key,secret=$this->secret]"; + } +} + +class OAuthToken { + // access tokens and request tokens + public $key; + public $secret; + + /** + * key = the token + * secret = the token secret + */ + function __construct($key, $secret) { + $this->key = $key; + $this->secret = $secret; + } + + /** + * generates the basic string serialization of a token that a server + * would respond to request_token and access_token calls with + */ + function to_string() { + return "oauth_token=" . + OAuthUtil::urlencode_rfc3986($this->key) . + "&oauth_token_secret=" . + OAuthUtil::urlencode_rfc3986($this->secret); + } + + function __toString() { + return $this->to_string(); + } +} + +/** + * A class for implementing a Signature Method + * See section 9 ("Signing Requests") in the spec + */ +abstract class OAuthSignatureMethod { + /** + * Needs to return the name of the Signature Method (ie HMAC-SHA1) + * @return string + */ + abstract public function get_name(); + + /** + * Build up the signature + * NOTE: The output of this function MUST NOT be urlencoded. + * the encoding is handled in OAuthRequest when the final + * request is serialized + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @return string + */ + abstract public function build_signature($request, $consumer, $token); + + /** + * Verifies that a given signature is correct + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @param string $signature + * @return bool + */ + public function check_signature($request, $consumer, $token, $signature) { + $built = $this->build_signature($request, $consumer, $token); + return $built == $signature; + } +} + +/** + * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] + * where the Signature Base String is the text and the key is the concatenated values (each first + * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' + * character (ASCII code 38) even if empty. + * - Chapter 9.2 ("HMAC-SHA1") + */ +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { + function get_name() { + return "HMAC-SHA1"; + } + + public function build_signature($request, $consumer, $token) { + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + + return base64_encode(hash_hmac('sha1', $base_string, $key, true)); + } +} + +/** + * The PLAINTEXT method does not provide any security protection and SHOULD only be used + * over a secure channel such as HTTPS. It does not use the Signature Base String. + * - Chapter 9.4 ("PLAINTEXT") + */ +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { + public function get_name() { + return "PLAINTEXT"; + } + + /** + * oauth_signature is set to the concatenated encoded values of the Consumer Secret and + * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is + * empty. The result MUST be encoded again. + * - Chapter 9.4.1 ("Generating Signatures") + * + * Please note that the second encoding MUST NOT happen in the SignatureMethod, as + * OAuthRequest handles this! + */ + public function build_signature($request, $consumer, $token) { + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + $request->base_string = $key; + + return $key; + } +} + +/** + * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in + * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for + * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a + * verified way to the Service Provider, in a manner which is beyond the scope of this + * specification. + * - Chapter 9.3 ("RSA-SHA1") + */ +abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { + public function get_name() { + return "RSA-SHA1"; + } + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // (2) fetch via http using a url provided by the requester + // (3) some sort of specific discovery code based on request + // + // Either way should return a string representation of the certificate + protected abstract function fetch_public_cert(&$request); + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // + // Either way should return a string representation of the certificate + protected abstract function fetch_private_cert(&$request); + + public function build_signature($request, $consumer, $token) { + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + // Fetch the private key cert based on the request + $cert = $this->fetch_private_cert($request); + + // Pull the private key ID from the certificate + $privatekeyid = openssl_get_privatekey($cert); + + // Sign using the key + $ok = openssl_sign($base_string, $signature, $privatekeyid); + + // Release the key resource + openssl_free_key($privatekeyid); + + return base64_encode($signature); + } + + public function check_signature($request, $consumer, $token, $signature) { + $decoded_sig = base64_decode($signature); + + $base_string = $request->get_signature_base_string(); + + // Fetch the public key cert based on the request + $cert = $this->fetch_public_cert($request); + + // Pull the public key ID from the certificate + $publickeyid = openssl_get_publickey($cert); + + // Check the computed signature against the one passed in the query + $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); + + // Release the key resource + openssl_free_key($publickeyid); + + return $ok == 1; + } +} + +class OAuthRequest { + private $parameters; + private $http_method; + private $http_url; + // for debug purposes + public $base_string; + public static $version = '1.0'; + public static $POST_INPUT = 'php://input'; + + function __construct($http_method, $http_url, $parameters=NULL) { + @$parameters or $parameters = array(); + $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); + $this->parameters = $parameters; + $this->http_method = $http_method; + $this->http_url = $http_url; + } + + + /** + * attempt to build up a request from what was passed to the server + */ + public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { + $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") + ? 'http' + : 'https'; + @$http_url or $http_url = $scheme . + '://' . $_SERVER['HTTP_HOST'] . + ':' . + $_SERVER['SERVER_PORT'] . + $_SERVER['REQUEST_URI']; + @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; + + // We weren't handed any parameters, so let's find the ones relevant to + // this request. + // If you run XML-RPC or similar you should use this to provide your own + // parsed parameter-list + if (!$parameters) { + // Find request headers + $request_headers = OAuthUtil::get_headers(); + + // Parse the query-string to find GET parameters + $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); + + // It's a POST request of the proper content-type, so parse POST + // parameters and add those overriding any duplicates from GET + if ($http_method == "POST" + && @strstr($request_headers["Content-Type"], + "application/x-www-form-urlencoded") + ) { + $post_data = OAuthUtil::parse_parameters( + file_get_contents(self::$POST_INPUT) + ); + $parameters = array_merge($parameters, $post_data); + } + + // We have a Authorization-header with OAuth data. Parse the header + // and add those overriding any duplicates from GET or POST + if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { + $header_parameters = OAuthUtil::split_header( + $request_headers['Authorization'] + ); + $parameters = array_merge($parameters, $header_parameters); + } + + } + + return new OAuthRequest($http_method, $http_url, $parameters); + } + + /** + * pretty much a helper function to set up the request + */ + public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { + @$parameters or $parameters = array(); + $defaults = array("oauth_version" => OAuthRequest::$version, + "oauth_nonce" => OAuthRequest::generate_nonce(), + "oauth_timestamp" => OAuthRequest::generate_timestamp(), + "oauth_consumer_key" => $consumer->key); + if ($token) + $defaults['oauth_token'] = $token->key; + + $parameters = array_merge($defaults, $parameters); + + return new OAuthRequest($http_method, $http_url, $parameters); + } + + public function set_parameter($name, $value, $allow_duplicates = true) { + if ($allow_duplicates && isset($this->parameters[$name])) { + // We have already added parameter(s) with this name, so add to the list + if (is_scalar($this->parameters[$name])) { + // This is the first duplicate, so transform scalar (string) + // into an array so we can add the duplicates + $this->parameters[$name] = array($this->parameters[$name]); + } + + $this->parameters[$name][] = $value; + } else { + $this->parameters[$name] = $value; + } + } + + public function get_parameter($name) { + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + } + + public function get_parameters() { + return $this->parameters; + } + + public function unset_parameter($name) { + unset($this->parameters[$name]); + } + + /** + * The request parameters, sorted and concatenated into a normalized string. + * @return string + */ + public function get_signable_parameters() { + // Grab all parameters + $params = $this->parameters; + + // Remove oauth_signature if present + // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") + if (isset($params['oauth_signature'])) { + unset($params['oauth_signature']); + } + + return OAuthUtil::build_http_query($params); + } + + /** + * Returns the base string of this request + * + * The base string defined as the method, the url + * and the parameters (normalized), each urlencoded + * and the concated with &. + */ + public function get_signature_base_string() { + $parts = array( + $this->get_normalized_http_method(), + $this->get_normalized_http_url(), + $this->get_signable_parameters() + ); + + $parts = OAuthUtil::urlencode_rfc3986($parts); + + return implode('&', $parts); + } + + /** + * just uppercases the http method + */ + public function get_normalized_http_method() { + return strtoupper($this->http_method); + } + + /** + * parses the url and rebuilds it to be + * scheme://host/path + */ + public function get_normalized_http_url() { + $parts = parse_url($this->http_url); + + $port = @$parts['port']; + $scheme = $parts['scheme']; + $host = $parts['host']; + $path = @$parts['path']; + + $port or $port = ($scheme == 'https') ? '443' : '80'; + + if (($scheme == 'https' && $port != '443') + || ($scheme == 'http' && $port != '80')) { + $host = "$host:$port"; + } + return "$scheme://$host$path"; + } + + /** + * builds a url usable for a GET request + */ + public function to_url() { + $post_data = $this->to_postdata(); + $out = $this->get_normalized_http_url(); + if ($post_data) { + $out .= '?'.$post_data; + } + return $out; + } + + /** + * builds the data one would send in a POST request + */ + public function to_postdata() { + return OAuthUtil::build_http_query($this->parameters); + } + + /** + * builds the Authorization: header + */ + public function to_header($realm=null) { + if($realm) + $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"'; + else + $out = 'Authorization: OAuth'; + + $total = array(); + foreach ($this->parameters as $k => $v) { + if (substr($k, 0, 5) != "oauth") continue; + if (is_array($v)) { + throw new OAuthException('Arrays not supported in headers'); + } + $out .= ',' . + OAuthUtil::urlencode_rfc3986($k) . + '="' . + OAuthUtil::urlencode_rfc3986($v) . + '"'; + } + return $out; + } + + public function __toString() { + return $this->to_url(); + } + + + public function sign_request($signature_method, $consumer, $token) { + $this->set_parameter( + "oauth_signature_method", + $signature_method->get_name(), + false + ); + $signature = $this->build_signature($signature_method, $consumer, $token); + $this->set_parameter("oauth_signature", $signature, false); + } + + public function build_signature($signature_method, $consumer, $token) { + $signature = $signature_method->build_signature($this, $consumer, $token); + return $signature; + } + + /** + * util function: current timestamp + */ + private static function generate_timestamp() { + return time(); + } + + /** + * util function: current nonce + */ + private static function generate_nonce() { + $mt = microtime(); + $rand = mt_rand(); + + return md5($mt . $rand); // md5s look nicer than numbers + } +} + +class OAuthServer { + protected $timestamp_threshold = 300; // in seconds, five minutes + protected $version = '1.0'; // hi blaine + protected $signature_methods = array(); + + protected $data_store; + + function __construct($data_store) { + $this->data_store = $data_store; + } + + public function add_signature_method($signature_method) { + $this->signature_methods[$signature_method->get_name()] = + $signature_method; + } + + // high level functions + + /** + * process a request_token request + * returns the request token on success + */ + public function fetch_request_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // no token required for the initial token request + $token = NULL; + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $callback = $request->get_parameter('oauth_callback'); + $new_token = $this->data_store->new_request_token($consumer, $callback); + + return $new_token; + } + + /** + * process an access_token request + * returns the access token on success + */ + public function fetch_access_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // requires authorized request token + $token = $this->get_token($request, $consumer, "request"); + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $verifier = $request->get_parameter('oauth_verifier'); + $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); + + return $new_token; + } + + /** + * verify an api call, checks all the parameters + */ + public function verify_request(&$request) { + $this->get_version($request); + $consumer = $this->get_consumer($request); + $token = $this->get_token($request, $consumer, "access"); + $this->check_signature($request, $consumer, $token); + return array($consumer, $token); + } + + // Internals from here + /** + * version 1 + */ + private function get_version(&$request) { + $version = $request->get_parameter("oauth_version"); + if (!$version) { + // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. + // Chapter 7.0 ("Accessing Protected Ressources") + $version = '1.0'; + } + if ($version !== $this->version) { + throw new OAuthException("OAuth version '$version' not supported"); + } + return $version; + } + + /** + * figure out the signature with some defaults + */ + private function get_signature_method(&$request) { + $signature_method = + @$request->get_parameter("oauth_signature_method"); + + if (!$signature_method) { + // According to chapter 7 ("Accessing Protected Ressources") the signature-method + // parameter is required, and we can't just fallback to PLAINTEXT + throw new OAuthException('No signature method parameter. This parameter is required'); + } + + if (!in_array($signature_method, + array_keys($this->signature_methods))) { + throw new OAuthException( + "Signature method '$signature_method' not supported " . + "try one of the following: " . + implode(", ", array_keys($this->signature_methods)) + ); + } + return $this->signature_methods[$signature_method]; + } + + /** + * try to find the consumer for the provided request's consumer key + */ + private function get_consumer(&$request) { + $consumer_key = @$request->get_parameter("oauth_consumer_key"); + if (!$consumer_key) { + throw new OAuthException("Invalid consumer key"); + } + + $consumer = $this->data_store->lookup_consumer($consumer_key); + if (!$consumer) { + throw new OAuthException("Invalid consumer"); + } + + return $consumer; + } + + /** + * try to find the token for the provided request's token key + */ + private function get_token(&$request, $consumer, $token_type="access") { + $token_field = @$request->get_parameter('oauth_token'); + $token = $this->data_store->lookup_token( + $consumer, $token_type, $token_field + ); + if (!$token) { + throw new OAuthException("Invalid $token_type token: $token_field"); + } + return $token; + } + + /** + * all-in-one function to check the signature on a request + * should guess the signature method appropriately + */ + private function check_signature(&$request, $consumer, $token) { + // this should probably be in a different method + $timestamp = @$request->get_parameter('oauth_timestamp'); + $nonce = @$request->get_parameter('oauth_nonce'); + + $this->check_timestamp($timestamp); + $this->check_nonce($consumer, $token, $nonce, $timestamp); + + $signature_method = $this->get_signature_method($request); + + $signature = $request->get_parameter('oauth_signature'); + $valid_sig = $signature_method->check_signature( + $request, + $consumer, + $token, + $signature + ); + + if (!$valid_sig) { + throw new OAuthException("Invalid signature"); + } + } + + /** + * check that the timestamp is new enough + */ + private function check_timestamp($timestamp) { + if( ! $timestamp ) + throw new OAuthException( + 'Missing timestamp parameter. The parameter is required' + ); + + // verify that timestamp is recentish + $now = time(); + if (abs($now - $timestamp) > $this->timestamp_threshold) { + throw new OAuthException( + "Expired timestamp, yours $timestamp, ours $now" + ); + } + } + + /** + * check that the nonce is not repeated + */ + private function check_nonce($consumer, $token, $nonce, $timestamp) { + if( ! $nonce ) + throw new OAuthException( + 'Missing nonce parameter. The parameter is required' + ); + + // verify that the nonce is uniqueish + $found = $this->data_store->lookup_nonce( + $consumer, + $token, + $nonce, + $timestamp + ); + if ($found) { + throw new OAuthException("Nonce already used: $nonce"); + } + } + +} + +class OAuthDataStore { + function lookup_consumer($consumer_key) { + // implement me + } + + function lookup_token($consumer, $token_type, $token) { + // implement me + } + + function lookup_nonce($consumer, $token, $nonce, $timestamp) { + // implement me + } + + function new_request_token($consumer, $callback = null) { + // return a new token attached to this consumer + } + + function new_access_token($token, $consumer, $verifier = null) { + // return a new access token attached to this consumer + // for the user associated with this token if the request token + // is authorized + // should also invalidate the request token + } + +} + +class OAuthUtil { + public static function urlencode_rfc3986($input) { + if (is_array($input)) { + return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); + } else if (is_scalar($input)) { + return str_replace( + '+', + ' ', + str_replace('%7E', '~', rawurlencode($input)) + ); + } else { + return ''; + } +} + + + // This decode function isn't taking into consideration the above + // modifications to the encoding process. However, this method doesn't + // seem to be used anywhere so leaving it as is. + public static function urldecode_rfc3986($string) { + return urldecode($string); + } + + // Utility function for turning the Authorization: header into + // parameters, has to do some unescaping + // Can filter out any non-oauth parameters if needed (default behaviour) + public static function split_header($header, $only_allow_oauth_parameters = true) { + $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/'; + $offset = 0; + $params = array(); + while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { + $match = $matches[0]; + $header_name = $matches[2][0]; + $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0]; + if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) { + $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content); + } + $offset = $match[1] + strlen($match[0]); + } + + if (isset($params['realm'])) { + unset($params['realm']); + } + + return $params; + } + + // helper to try to sort out headers for people who aren't running apache + public static function get_headers() { + if (function_exists('apache_request_headers')) { + // we need this to get the actual Authorization: header + // because apache tends to tell us it doesn't exist + $headers = apache_request_headers(); + + // sanitize the output of apache_request_headers because + // we always want the keys to be Cased-Like-This and arh() + // returns the headers in the same case as they are in the + // request + $out = array(); + foreach( $headers AS $key => $value ) { + $key = str_replace( + " ", + "-", + ucwords(strtolower(str_replace("-", " ", $key))) + ); + $out[$key] = $value; + } + } else { + // otherwise we don't have apache and are just going to have to hope + // that $_SERVER actually contains what we need + $out = array(); + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) == "HTTP_") { + // this is chaos, basically it is just there to capitalize the first + // letter of every word that is not an initial HTTP and strip HTTP + // code from przemek + $key = str_replace( + " ", + "-", + ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) + ); + $out[$key] = $value; + } + } + } + return $out; + } + + // This function takes a input like a=b&a=c&d=e and returns the parsed + // parameters like this + // array('a' => array('b','c'), 'd' => 'e') + public static function parse_parameters( $input ) { + if (!isset($input) || !$input) return array(); + + $pairs = explode('&', $input); + + $parsed_parameters = array(); + foreach ($pairs as $pair) { + $split = explode('=', $pair, 2); + $parameter = OAuthUtil::urldecode_rfc3986($split[0]); + $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; + + if (isset($parsed_parameters[$parameter])) { + // We have already recieved parameter(s) with this name, so add to the list + // of parameters with this name + + if (is_scalar($parsed_parameters[$parameter])) { + // This is the first duplicate, so transform scalar (string) into an array + // so we can add the duplicates + $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]); + } + + $parsed_parameters[$parameter][] = $value; + } else { + $parsed_parameters[$parameter] = $value; + } + } + return $parsed_parameters; + } + + public static function build_http_query($params) { + if (!$params) return ''; + + // Urlencode both keys and values + $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); + $values = OAuthUtil::urlencode_rfc3986(array_values($params)); + $params = array_combine($keys, $values); + + // Parameters are sorted by name, using lexicographical byte value ordering. + // Ref: Spec: 9.1.1 (1) + uksort($params, 'strcmp'); + + $pairs = array(); + foreach ($params as $parameter => $value) { + if (is_array($value)) { + // If two or more parameters share the same name, they are sorted by their value + // Ref: Spec: 9.1.1 (1) + natsort($value); + foreach ($value as $duplicate_value) { + $pairs[] = $parameter . '=' . $duplicate_value; + } + } else { + $pairs[] = $parameter . '=' . $value; + } + } + // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) + // Each name-value pair is separated by an '&' character (ASCII code 38) + return implode('&', $pairs); + } +} + +?> diff --git a/pacotes/linkedinoauth/OAuthTests.xml b/pacotes/linkedinoauth/OAuthTests.xml new file mode 100644 index 0000000..39122a1 --- /dev/null +++ b/pacotes/linkedinoauth/OAuthTests.xml @@ -0,0 +1,13 @@ + + + tests + + + + tests + + + + + + \ No newline at end of file diff --git a/pacotes/linkedinoauth/OAuth_TestServer.php b/pacotes/linkedinoauth/OAuth_TestServer.php new file mode 100644 index 0000000..3cf3518 --- /dev/null +++ b/pacotes/linkedinoauth/OAuth_TestServer.php @@ -0,0 +1,106 @@ +signature_methods; + } +} + +class TestOAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod_RSA_SHA1 { + public function fetch_private_cert(&$request) { + $cert = <<consumer = new OAuthConsumer("key", "secret", NULL); + $this->request_token = new OAuthToken("requestkey", "requestsecret", 1); + $this->access_token = new OAuthToken("accesskey", "accesssecret", 1); + $this->nonce = "nonce"; + }/*}}}*/ + + function lookup_consumer($consumer_key) {/*{{{*/ + if ($consumer_key == $this->consumer->key) return $this->consumer; + return NULL; + }/*}}}*/ + + function lookup_token($consumer, $token_type, $token) {/*{{{*/ + $token_attrib = $token_type . "_token"; + if ($consumer->key == $this->consumer->key + && $token == $this->$token_attrib->key) { + return $this->$token_attrib; + } + return NULL; + }/*}}}*/ + + function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ + if ($consumer->key == $this->consumer->key + && (($token && $token->key == $this->request_token->key) + || ($token && $token->key == $this->access_token->key)) + && $nonce == $this->nonce) { + return $this->nonce; + } + return NULL; + }/*}}}*/ + + function new_request_token($consumer) {/*{{{*/ + if ($consumer->key == $this->consumer->key) { + return $this->request_token; + } + return NULL; + }/*}}}*/ + + function new_access_token($token, $consumer) {/*{{{*/ + if ($consumer->key == $this->consumer->key + && $token->key == $this->request_token->key) { + return $this->access_token; + } + return NULL; + }/*}}}*/ +}/*}}}*/ +?> diff --git a/pacotes/linkedinoauth/doc/design.txt b/pacotes/linkedinoauth/doc/design.txt new file mode 100644 index 0000000..e9ce77b --- /dev/null +++ b/pacotes/linkedinoauth/doc/design.txt @@ -0,0 +1,68 @@ +Interfaces: + +# OAuthConsumer is a data type that represents the identity of the Consumer +# via its shared secret with the Service Provider. +OAuthConsumer + - key : str + - secret : str + +# OAuthToken is a data type that represents an End User via either an access +# or request token +OAuthToken + - token : str + - secret : str + - to_string() -> str + - (static) from_string() -> OAuthToken + +# OAuthSignatureMethod is a strategy class that implements a signature method +OAuthSignatureMethod + - get_name() -> str + - build_signature (OAuthRequest, OAuthConsumer, OAuthToken) -> str + +# OAuthRequest represents the request and can be seriali +OAuthRequest: + - OAuthRequest(str http_method, str http_url, [dict parameters]) -> constructor + - set_parameter(str parameter, str value) -> void + - example parameters: oauth_consumer_key, foo + - get_parameter(str parameter) -> str + - get_parameters() -> dict + + - get_normalized_http_method() -> str + - get_normalized_http_url() -> str + - get_signable_params() -> dict + + - to_header () -> str # serialize as a header for an HTTPAuth request + - to_postdata () -> str # serialize as post data for a POST request + - to_url () -> str # serialize as a url for a GET request + - sign_request(OAuthSignatureMethod, OAuthConsumer, OAuthToken) -> void + - build_signature(OAuthSignatureMethod, OAuthConsumer, OAuthToken) -> str + - (static) from_request([str http_method, str http_url, dict parameters]) + - (static) from_consumer_and_token(OAuthConsumer, OAuthToken, str http_method, str http_url, [dict parameters]) -> OAuthRequest + + +# OAuthServer is a worker to check a requests validity against a data store +OAuthServer: + - OAuthServer(OAuthDataStore) -> constructor + - set_data_store(OAuthDataStore) -> void + - get_data_store() -> OAuthDataStore + + - fetch_request_token (OAuthRequest) -> OAuthToken + - fetch_access_token (OAuthRequest) -> OAuthToken + - verify_request (OAuthRequest) -> OAuthToken + +# OAuthClient is a worker to attempt to execute a request +OAuthClient: + - OAuthClient(OAuthConsumer, OAuthToken) -> constructor + - get_consumer() -> OAuthConsumer + - get_token() -> OAuthToken + + - fetch_request_token (OAuthRequest) -> OAuthToken + - fetch_access_token (OAuthRequest) -> OAuthToken + +# OAuthDataStore is a database abstraction used to lookup consumers and tokens +OAuthDataStore: + - lookup_consumer(str key) -> OAuthConsumer + - lookup_token(OAuthConsumer, str token_type, str token_token) -> OAuthToken + - lookup_nonce(OAuthConsumer, OAuthToken, str nonce, int timestamp) -> OAuthToken + - fetch_request_token(OAuthConsumer) -> OAuthToken + - fetch_access_token(OAuthConsumer, OAuthToken) -> OAuthToken diff --git a/pacotes/linkedinoauth/example/SimpleOAuthDataStore.php b/pacotes/linkedinoauth/example/SimpleOAuthDataStore.php new file mode 100644 index 0000000..98474d6 --- /dev/null +++ b/pacotes/linkedinoauth/example/SimpleOAuthDataStore.php @@ -0,0 +1,74 @@ +dbh = dba_popen($path, 'c', 'gdbm'); + }/*}}}*/ + + function __destruct() {/*{{{*/ + dba_close($this->dbh); + }/*}}}*/ + + function lookup_consumer($consumer_key) {/*{{{*/ + $rv = dba_fetch("consumer_$consumer_key", $this->dbh); + if ($rv === FALSE) { + return NULL; + } + $obj = unserialize($rv); + if (!($obj instanceof OAuthConsumer)) { + return NULL; + } + return $obj; + }/*}}}*/ + + function lookup_token($consumer, $token_type, $token) {/*{{{*/ + $rv = dba_fetch("${token_type}_${token}", $this->dbh); + if ($rv === FALSE) { + return NULL; + } + $obj = unserialize($rv); + if (!($obj instanceof OAuthToken)) { + return NULL; + } + return $obj; + }/*}}}*/ + + function lookup_nonce($consumer, $token, $nonce, $timestamp) {/*{{{*/ + if (dba_exists("nonce_$nonce", $this->dbh)) { + return TRUE; + } else { + dba_insert("nonce_$nonce", "1", $this->dbh); + return FALSE; + } + }/*}}}*/ + + function new_token($consumer, $type="request") {/*{{{*/ + $key = md5(time()); + $secret = time() + time(); + $token = new OAuthToken($key, md5(md5($secret))); + if (!dba_insert("${type}_$key", serialize($token), $this->dbh)) { + throw new OAuthException("doooom!"); + } + return $token; + }/*}}}*/ + + function new_request_token($consumer) {/*{{{*/ + return $this->new_token($consumer, "request"); + }/*}}}*/ + + function new_access_token($token, $consumer) {/*{{{*/ + + $token = $this->new_token($consumer, 'access'); + dba_delete("request_" . $token->key, $this->dbh); + return $token; + }/*}}}*/ +}/*}}}*/ \ No newline at end of file diff --git a/pacotes/linkedinoauth/example/access_token.php b/pacotes/linkedinoauth/example/access_token.php new file mode 100644 index 0000000..737a644 --- /dev/null +++ b/pacotes/linkedinoauth/example/access_token.php @@ -0,0 +1,14 @@ +fetch_access_token($req); + print $token; +} catch (OAuthException $e) { + print($e->getMessage() . "\n
\n"); + print_r($req); + die(); +} + +?> diff --git a/pacotes/linkedinoauth/example/client.php b/pacotes/linkedinoauth/example/client.php new file mode 100644 index 0000000..5c5ab63 --- /dev/null +++ b/pacotes/linkedinoauth/example/client.php @@ -0,0 +1,133 @@ +sign_request($sig_method, $test_consumer, NULL); + if ($dump_request) { + Header('Content-type: text/plain'); + print "request url: " . $req_req->to_url(). "\n"; + print_r($req_req); + exit; + } + Header("Location: $req_req"); +} +else if ($action == "authorize") { + $callback_url = "$base_url/client.php?key=$key&secret=$secret&token=$token&token_secret=$token_secret&endpoint=" . urlencode($endpoint); + $auth_url = $endpoint . "?oauth_token=$token&oauth_callback=".urlencode($callback_url); + if ($dump_request) { + Header('Content-type: text/plain'); + print("auth_url: " . $auth_url); + exit; + } + Header("Location: $auth_url"); +} +else if ($action == "access_token") { + $parsed = parse_url($endpoint); + $params = array(); + parse_str($parsed['query'], $params); + + $acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, "GET", $endpoint, $params); + $acc_req->sign_request($sig_method, $test_consumer, $test_token); + if ($dump_request) { + Header('Content-type: text/plain'); + print "request url: " . $acc_req->to_url() . "\n"; + print_r($acc_req); + exit; + } + Header("Location: $acc_req"); +} + +?> + + +OAuth Test Client + + +
server | client
+

OAuth Test Client

+

Instructions for Use

+

This is a test client that will let you test your OAuth server code. Enter the appropriate information below to test.

+

Note: we don't store any of the information you type in.

+ +
+

Choose a Signature Method

+ +

Enter The Endpoint to Test

+endpoint:
+Note: You can include query parameters in there to have them parsed in and signed too +

Enter Your Consumer Key / Secret

+consumer key:
+consumer secret:
+dump request, don't redirect: />
+make a token request (don't forget to copy down the values you get) + +

Enter Your Request Token / Secret

+token:
+token secret:
+

Don't forget to update your endpoint to point at the auth or access token url

+try to authorize this token:
+try to get an access token:
+ +

Currently Supported Signature Methods

+

Current signing method is: get_name() ?>

+
    + $method) { + + print "
  • $key"; + if ($key != $sig_method->get_name()) { + print "(switch)"; + } + print "
  • \n"; +} +?> +
+ +get_name()) { + // passing test_server as a dummy referecne + print "
" . $sig_method->fetch_private_cert($test_server). "
\n"; + print "
" . $sig_method->fetch_public_cert($test_server) . "
\n"; +} +?> + +

Further Resources

+

There is also a test server implementation in here.

+

The code running this example can be downloaded from the PHP section of the OAuth google code project: http://code.google.com/p/oauth/ + diff --git a/pacotes/linkedinoauth/example/common.inc.php b/pacotes/linkedinoauth/example/common.inc.php new file mode 100644 index 0000000..c8c8e7f --- /dev/null +++ b/pacotes/linkedinoauth/example/common.inc.php @@ -0,0 +1,27 @@ +add_signature_method($hmac_method); +$test_server->add_signature_method($plaintext_method); +$test_server->add_signature_method($rsa_method); + +$sig_methods = $test_server->get_signature_methods(); +?> diff --git a/pacotes/linkedinoauth/example/echo_api.php b/pacotes/linkedinoauth/example/echo_api.php new file mode 100644 index 0000000..a79173f --- /dev/null +++ b/pacotes/linkedinoauth/example/echo_api.php @@ -0,0 +1,21 @@ +verify_request($req); + + // lsit back the non-OAuth params + $total = array(); + foreach($req->get_parameters() as $k => $v) { + if (substr($k, 0, 5) == "oauth") continue; + $total[] = urlencode($k) . "=" . urlencode($v); + } + print implode("&", $total); +} catch (OAuthException $e) { + print($e->getMessage() . "\n


\n"); + print_r($req); + die(); +} + +?> diff --git a/pacotes/linkedinoauth/example/index.php b/pacotes/linkedinoauth/example/index.php new file mode 100644 index 0000000..5039de0 --- /dev/null +++ b/pacotes/linkedinoauth/example/index.php @@ -0,0 +1,108 @@ +sign_request($sig_method, $test_consumer, NULL); + +$acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $req_token, "GET", $base_url . "/access_token.php"); +$acc_req->sign_request($sig_method, $test_consumer, $req_token); + +$echo_req = OAuthRequest::from_consumer_and_token($test_consumer, $acc_token, "GET", $base_url . "/echo_api.php", array("method"=> "foo%20bar", "bar" => "baz")); +$echo_req->sign_request($sig_method, $test_consumer, $acc_token); + +?> + + +OAuth Test Server + + +
server | client
+

OAuth Test Server

+

Instructions for Use

+

This is a test server with a predefined static set of keys and tokens, you can make your requests using them to test your code (and mine ;)).

+

Your Consumer Key / Secret

+
    +
  • consumer key: key
  • +
  • consumer secret: secret
  • +
+

Use this key and secret for all your requests.

+

Getting a Request Token

+ +
    +
  • request token endpoint:
  • +
+ +

A successful request will return the following:

+

oauth_token=requestkey&oauth_token_secret=requestsecret

+ +

An unsuccessful request will attempt to describe what went wrong.

+ +

Example

+ + +

Getting an Access Token

+

The Request Token provided above is already authorized, you may use it to request an Access Token right away.

+ +
    +
  • access token endpoint:
  • +
+ +

A successful request will return the following:

+

oauth_token=accesskey&oauth_token_secret=accesssecret

+ +

An unsuccessful request will attempt to describe what went wrong.

+ +

Example

+ + +

Making Authenticated Calls

+

Using your Access Token you can make authenticated calls.

+ +
    +
  • api endpoint:
  • +
+

+A successful request will echo the non-OAuth parameters sent to it, for example:

+

method=foo&bar=baz

+

An unsuccessful request will attempt to describe what went wrong.

+ +

Example

+ + +

Currently Supported Signature Methods

+

Current signing method is:

+
    +get_signature_methods(); +foreach ($sig_methods as $key => $method) { + print "
  • $key"; + if ($key != $sig_method->get_name()) { + print "(switch)"; + } + print "
  • \n"; +} +?> +
+ +get_name()) { + print "
" . $sig_method->fetch_private_cert($req_req) . "
\n"; + print "
" . $sig_method->fetch_public_cert($req_req) . "
\n"; +} +?> + +

Further Resources

+

There is also a test client implementation in here.

+

The code running this example can be downloaded from the PHP section of the OAuth google code project: http://code.google.com/p/oauth/ + diff --git a/pacotes/linkedinoauth/example/request_token.php b/pacotes/linkedinoauth/example/request_token.php new file mode 100644 index 0000000..f6c02f4 --- /dev/null +++ b/pacotes/linkedinoauth/example/request_token.php @@ -0,0 +1,14 @@ +fetch_request_token($req); + print $token; +} catch (OAuthException $e) { + print($e->getMessage() . "\n


\n"); + print_r($req); + die(); +} + +?> diff --git a/pacotes/linkedinoauth/linkedin.php b/pacotes/linkedinoauth/linkedin.php new file mode 100644 index 0000000..447484f --- /dev/null +++ b/pacotes/linkedinoauth/linkedin.php @@ -0,0 +1,139 @@ +oauth_callback = $oauth_callback; + } + + $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret, $this->oauth_callback); + $this->signature_method = new OAuthSignatureMethod_HMAC_SHA1(); + $this->request_token_path = $this->secure_base_url . "/uas/oauth/requestToken"; + $this->access_token_path = $this->secure_base_url . "/uas/oauth/accessToken"; + $this->authorize_path = $this->secure_base_url . "/uas/oauth/authorize"; + + } + + function getRequestToken() { + $consumer = $this->consumer; + $request = OAuthRequest::from_consumer_and_token($consumer, NULL, "GET", $this->request_token_path); + $request->set_parameter("oauth_callback", $this->oauth_callback); + $request->sign_request($this->signature_method, $consumer, NULL); + $headers = Array(); + $url = $request->to_url(); + $response = $this->httpRequest($url, $headers, "GET"); + parse_str($response, $response_params); + $this->request_token = new OAuthConsumer($response_params['oauth_token'], $response_params['oauth_token_secret'], 1); + } + + function generateAuthorizeUrl() { + $consumer = $this->consumer; + $request_token = $this->request_token; + return $this->authorize_path . "?oauth_token=" . $request_token->key; + } + + function getAccessToken($oauth_verifier) { + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->request_token, "GET", $this->access_token_path); + $request->set_parameter("oauth_verifier", $oauth_verifier); + $request->sign_request($this->signature_method, $this->consumer, $this->request_token); + $headers = Array(); + $url = $request->to_url(); + $response = $this->httpRequest($url, $headers, "GET"); + parse_str($response, $response_params); + if($debug) { + echo $response . "\n"; + } + $this->access_token = new OAuthConsumer($response_params['oauth_token'], $response_params['oauth_token_secret'], 1); + } + + function getProfile($resource = "~") { + $profile_url = $this->base_url . "/v1/people/" . $resource; + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->access_token, "GET", $profile_url); + $request->sign_request($this->signature_method, $this->consumer, $this->access_token); + $auth_header = $request->to_header("https://api.linkedin.com"); # this is the realm + # This PHP library doesn't generate the header correctly when a realm is not specified. + # Make sure there is a space and not a comma after OAuth + // $auth_header = preg_replace("/Authorization\: OAuth\,/", "Authorization: OAuth ", $auth_header); + // # Make sure there is a space between OAuth attribute + // $auth_header = preg_replace('/\"\,/', '", ', $auth_header); + if ($debug) { + echo $auth_header; + } + // $response will now hold the XML document + $response = $this->httpRequest($profile_url, $auth_header, "GET"); + return $response; + } + + function setStatus($status) { + $status_url = $this->base_url . "/v1/people/~/current-status"; + echo "Setting status...\n"; + $xml = "" . htmlspecialchars($status, ENT_NOQUOTES, "UTF-8") . ""; + echo $xml . "\n"; + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->access_token, "PUT", $status_url); + $request->sign_request($this->signature_method, $this->consumer, $this->access_token); + $auth_header = $request->to_header("https://api.linkedin.com"); + if ($debug) { + echo $auth_header . "\n"; + } + $response = $this->httpRequest($profile_url, $auth_header, "GET"); + return $response; + } + + # Parameters should be a query string starting with "?" + # Example search("?count=10&start=10&company=LinkedIn"); + function search($parameters) { + $search_url = $this->base_url . "/v1/people/" . $parameters; + echo "Performing search for: " . $parameters . "\n"; + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->access_token, "GET", $search_url); + $request->sign_request($this->signature_method, $this->consumer, $this->access_token); + $auth_header = $request->to_header("https://api.linkedin.com"); + if ($debug) { + echo $request->get_signature_base_string() . "\n"; + echo $auth_header . "\n"; + } + $response = $this->httpRequest($search_url, $auth_header, "GET"); + return $response; + } + + function httpRequest($url, $auth_header, $method, $body = NULL) { + if (!$method) { + $method = "GET"; + }; + + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_HEADER, 0); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_HTTPHEADER, array($auth_header)); // Set the headers. + + if ($body) { + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, $body); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); + curl_setopt($curl, CURLOPT_HTTPHEADER, array($auth_header, "Content-Type: text/xml;charset=utf-8")); + } + + $data = curl_exec($curl); + if ($this->debug) { + echo $data . "\n"; + } + curl_close($curl); + return $data; + } + +} diff --git a/pacotes/linkedinoauth/testLinkedinOauth.php b/pacotes/linkedinoauth/testLinkedinOauth.php new file mode 100644 index 0000000..726b778 --- /dev/null +++ b/pacotes/linkedinoauth/testLinkedinOauth.php @@ -0,0 +1,39 @@ +"; +# First step is to initialize with your consumer key and secret. We'll use an out-of-band oauth_callback +$linkedin = new LinkedIn($consumer_key, $consumer_secret, "oob"); +$linkedin->debug = true; + +# Now we retrieve a request token. It will be set as $linkedin->request_token +$linkedin->getRequestToken(); + +# With a request token in hand, we can generate an authorization URL, which we'll direct the user to +echo "Authorization URL: " . $linkedin->generateAuthorizeUrl() . "\n\n"; + +# After logging in, the user will be presented with an OAuth Verifier, which you would then ask the member to enter in a UI you present. Once you have the OAuth verifier, set it here: + +echo "Enter OAuth Verifier:\n"; +$handle = fopen("php://stdin", "r"); +$oauth_verifier = trim(fgets($handle)); + +$linkedin->getAccessToken($oauth_verifier); + +# You now have a $linkedin->access_token and can make calls on behalf of the current member +$xml_response = $linkedin->getProfile("~:(id,first-name,last-name,headline,picture-url)"); + +echo $xml_response; + +# Let's set our status + +$xml_response2 = $linkedin->setStatus("setting my status using the LinkedIn API."); +echo $xml_response2; + +# Let's do a search! +$search_response = $linkedin->search("?company=Google&count=10"); +echo $search_response; + +?> diff --git a/pacotes/linkedinoauth/testWithAcessToken.php b/pacotes/linkedinoauth/testWithAcessToken.php new file mode 100644 index 0000000..5df4fba --- /dev/null +++ b/pacotes/linkedinoauth/testWithAcessToken.php @@ -0,0 +1,22 @@ +debug = true; + +$linkedin->access_token = new OAuthConsumer($access_token, $access_token_secret, 1); + +# Let's do a search! +$search_response = $linkedin->search("?company=Google&count=10"); + +echo $search_response; + +?> diff --git a/pacotes/linkedinoauth/tests/Mock_OAuthBaseStringRequest.php b/pacotes/linkedinoauth/tests/Mock_OAuthBaseStringRequest.php new file mode 100644 index 0000000..53cd119 --- /dev/null +++ b/pacotes/linkedinoauth/tests/Mock_OAuthBaseStringRequest.php @@ -0,0 +1,12 @@ +provided_base_string = $bs; } + public function get_signature_base_string() { return $this->provided_base_string; } +} diff --git a/pacotes/linkedinoauth/tests/Mock_OAuthDataStore.php b/pacotes/linkedinoauth/tests/Mock_OAuthDataStore.php new file mode 100644 index 0000000..30680ee --- /dev/null +++ b/pacotes/linkedinoauth/tests/Mock_OAuthDataStore.php @@ -0,0 +1,57 @@ +consumer = new OAuthConsumer("key", "secret", NULL); + $this->request_token = new OAuthToken("requestkey", "requestsecret", 1); + $this->access_token = new OAuthToken("accesskey", "accesssecret", 1); + $this->nonce = "nonce"; + } + + function lookup_consumer($consumer_key) { + if ($consumer_key == $this->consumer->key) return $this->consumer; + return NULL; + } + + function lookup_token($consumer, $token_type, $token) { + $token_attrib = $token_type . "_token"; + if ($consumer->key == $this->consumer->key + && $token == $this->$token_attrib->key) { + return $this->$token_attrib; + } + return NULL; + } + + function lookup_nonce($consumer, $token, $nonce, $timestamp) { + if ($consumer->key == $this->consumer->key + && (($token && $token->key == $this->request_token->key) + || ($token && $token->key == $this->access_token->key)) + && $nonce == $this->nonce) { + return $this->nonce; + } + return NULL; + } + + function new_request_token($consumer) { + if ($consumer->key == $this->consumer->key) { + return $this->request_token; + } + return NULL; + } + + function new_access_token($token, $consumer) { + if ($consumer->key == $this->consumer->key + && $token->key == $this->request_token->key) { + return $this->access_token; + } + return NULL; + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php b/pacotes/linkedinoauth/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php new file mode 100644 index 0000000..aa893c8 --- /dev/null +++ b/pacotes/linkedinoauth/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php @@ -0,0 +1,47 @@ +assertEquals('OAuthConsumer[key=key,secret=secret]', (string) $consumer); + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthRequestTest.php b/pacotes/linkedinoauth/tests/OAuthRequestTest.php new file mode 100644 index 0000000..3b02176 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthRequestTest.php @@ -0,0 +1,317 @@ +'foo')); + $this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to read back parameter'); + + $request = new OAuthRequest('', '', array('test'=>array('foo', 'bar'))); + $this->assertEquals( array('foo', 'bar'), $request->get_parameter('test'), 'Failed to read back parameter'); + + + $request = new OAuthRequest('', '', array('test'=>'foo', 'bar'=>'baz')); + $this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to read back parameter'); + $this->assertEquals( 'baz', $request->get_parameter('bar'), 'Failed to read back parameter'); + } + + public function testGetAllParameters() { + // Yes, a awesomely boring test.. But if this doesn't work, the other tests is unreliable + $request = new OAuthRequest('', '', array('test'=>'foo')); + $this->assertEquals( array('test'=>'foo'), $request->get_parameters(), 'Failed to read back parameters'); + + $request = new OAuthRequest('', '', array('test'=>'foo', 'bar'=>'baz')); + $this->assertEquals( array('test'=>'foo', 'bar'=>'baz'), $request->get_parameters(), 'Failed to read back parameters'); + + $request = new OAuthRequest('', '', array('test'=>array('foo', 'bar'))); + $this->assertEquals( array('test'=>array('foo', 'bar')), $request->get_parameters(), 'Failed to read back parameters'); + } + + public function testSetParameters() { + $request = new OAuthRequest('', ''); + $this->assertEquals( NULL, $request->get_parameter('test'), 'Failed to assert that non-existing parameter is NULL'); + + $request->set_parameter('test', 'foo'); + $this->assertEquals( 'foo', $request->get_parameter('test'), 'Failed to set single-entry parameter'); + + $request->set_parameter('test', 'bar'); + $this->assertEquals( array('foo', 'bar'), $request->get_parameter('test'), 'Failed to set single-entry parameter'); + + $request->set_parameter('test', 'bar', false); + $this->assertEquals( 'bar', $request->get_parameter('test'), 'Failed to set single-entry parameter'); + } + + public function testUnsetParameter() { + $request = new OAuthRequest('', ''); + $this->assertEquals( NULL, $request->get_parameter('test')); + + $request->set_parameter('test', 'foo'); + $this->assertEquals( 'foo', $request->get_parameter('test')); + + $request->unset_parameter('test'); + $this->assertEquals( NULL, $request->get_parameter('test'), 'Failed to unset parameter'); + } + + public function testCreateRequestFromConsumerAndToken() { + $cons = new OAuthConsumer('key', 'kd94hf93k423kf44'); + $token = new OAuthToken('token', 'pfkkdhi9sl3r4s00'); + + $request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com'); + $this->assertEquals('POST', $request->get_normalized_http_method()); + $this->assertEquals('http://example.com', $request->get_normalized_http_url()); + $this->assertEquals('1.0', $request->get_parameter('oauth_version')); + $this->assertEquals($cons->key, $request->get_parameter('oauth_consumer_key')); + $this->assertEquals($token->key, $request->get_parameter('oauth_token')); + $this->assertEquals(time(), $request->get_parameter('oauth_timestamp')); + $this->assertRegExp('/[0-9a-f]{32}/', $request->get_parameter('oauth_nonce')); + // We don't know what the nonce will be, except it'll be md5 and hence 32 hexa digits + + $request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com', array('oauth_nonce'=>'foo')); + $this->assertEquals('foo', $request->get_parameter('oauth_nonce')); + + $request = OAuthRequest::from_consumer_and_token($cons, NULL, 'POST', 'http://example.com', array('oauth_nonce'=>'foo')); + $this->assertNull($request->get_parameter('oauth_token')); + + // Test that parameters given in the $http_url instead of in the $parameters-parameter + // will still be picked up + $request = OAuthRequest::from_consumer_and_token($cons, $token, 'POST', 'http://example.com/?foo=bar'); + $this->assertEquals('http://example.com/', $request->get_normalized_http_url()); + $this->assertEquals('bar', $request->get_parameter('foo')); + } + + public function testBuildRequestFromPost() { + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'foo=bar&baz=blargh'); + $this->assertEquals(array('foo'=>'bar','baz'=>'blargh'), OAuthRequest::from_request()->get_parameters(), 'Failed to parse POST parameters'); + } + + public function testBuildRequestFromGet() { + OAuthTestUtils::build_request('GET', 'http://testbed/test?foo=bar&baz=blargh'); + $this->assertEquals(array('foo'=>'bar','baz'=>'blargh'), OAuthRequest::from_request()->get_parameters(), 'Failed to parse GET parameters'); + } + + public function testBuildRequestFromHeader() { + $test_header = 'OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"'; + OAuthTestUtils::build_request('POST', 'http://testbed/test', '', $test_header); + $this->assertEquals(array('oauth_foo'=>'bar','oauth_baz'=>'bla,rgh'), OAuthRequest::from_request()->get_parameters(), 'Failed to split auth-header correctly'); + } + + public function testHasProperParameterPriority() { + $test_header = 'OAuth realm="",oauth_foo=header'; + OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get', 'oauth_foo=post', $test_header); + $this->assertEquals('header', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities'); + + OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get', 'oauth_foo=post'); + $this->assertEquals('post', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities'); + + OAuthTestUtils::build_request('POST', 'http://testbed/test?oauth_foo=get'); + $this->assertEquals('get', OAuthRequest::from_request()->get_parameter('oauth_foo'), 'Loaded parameters in with the wrong priorities'); + } + + public function testNormalizeHttpMethod() { + OAuthTestUtils::build_request('POST', 'http://testbed/test'); + $this->assertEquals('POST', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: POST'); + + OAuthTestUtils::build_request('post', 'http://testbed/test'); + $this->assertEquals('POST', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: post'); + + OAuthTestUtils::build_request('GET', 'http://testbed/test'); + $this->assertEquals('GET', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: GET'); + + OAuthTestUtils::build_request('PUT', 'http://testbed/test'); + $this->assertEquals('PUT', OAuthRequest::from_request()->get_normalized_http_method(), 'Failed to normalize HTTP method: PUT'); + } + + public function testNormalizeParameters() { + // This is mostly repeats of OAuthUtilTest::testParseParameters & OAuthUtilTest::TestBuildHttpQuery + + // Tests taken from + // http://wiki.oauth.net/TestCases ("Normalize Request Parameters") + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'name'); + $this->assertEquals( 'name=', OAuthRequest::from_request()->get_signable_parameters()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=b'); + $this->assertEquals( 'a=b', OAuthRequest::from_request()->get_signable_parameters()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=b&c=d'); + $this->assertEquals( 'a=b&c=d', OAuthRequest::from_request()->get_signable_parameters()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=x%21y&a=x+y'); + $this->assertEquals( 'a=x%20y&a=x%21y', OAuthRequest::from_request()->get_signable_parameters()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'x%21y=a&x=a'); + $this->assertEquals( 'x=a&x%21y=a', OAuthRequest::from_request()->get_signable_parameters()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'a=1&c=hi there&f=25&f=50&f=a&z=p&z=t'); + $this->assertEquals( 'a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t', OAuthRequest::from_request()->get_signable_parameters()); + } + + public function testNormalizeHttpUrl() { + OAuthTestUtils::build_request('POST', 'http://example.com'); + $this->assertEquals('http://example.com', OAuthRequest::from_request()->get_normalized_http_url()); + + OAuthTestUtils::build_request('POST', 'https://example.com'); + $this->assertEquals('https://example.com', OAuthRequest::from_request()->get_normalized_http_url()); + + // Tests that http on !80 and https on !443 keeps the port + OAuthTestUtils::build_request('POST', 'http://example.com:8080'); + $this->assertEquals('http://example.com:8080', OAuthRequest::from_request()->get_normalized_http_url()); + + OAuthTestUtils::build_request('POST', 'https://example.com:80'); + $this->assertEquals('https://example.com:80', OAuthRequest::from_request()->get_normalized_http_url()); + + OAuthTestUtils::build_request('POST', 'http://example.com:443'); + $this->assertEquals('http://example.com:443', OAuthRequest::from_request()->get_normalized_http_url()); + } + + public function testBuildPostData() { + OAuthTestUtils::build_request('POST', 'http://example.com'); + $this->assertEquals('', OAuthRequest::from_request()->to_postdata()); + + OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar'); + $this->assertEquals('foo=bar', OAuthRequest::from_request()->to_postdata()); + + OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar'); + $this->assertEquals('foo=bar', OAuthRequest::from_request()->to_postdata()); + } + + public function testBuildUrl() { + OAuthTestUtils::build_request('POST', 'http://example.com'); + $this->assertEquals('http://example.com', OAuthRequest::from_request()->to_url()); + + OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar'); + $this->assertEquals('http://example.com?foo=bar', OAuthRequest::from_request()->to_url()); + + OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar'); + $this->assertEquals('http://example.com?foo=bar', OAuthRequest::from_request()->to_url()); + } + + public function testConvertToString() { + OAuthTestUtils::build_request('POST', 'http://example.com'); + $this->assertEquals('http://example.com', (string) OAuthRequest::from_request()); + + OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar'); + $this->assertEquals('http://example.com?foo=bar', (string) OAuthRequest::from_request()); + + OAuthTestUtils::build_request('GET', 'http://example.com?foo=bar'); + $this->assertEquals('http://example.com?foo=bar', (string) OAuthRequest::from_request()); + } + + public function testBuildHeader() { + OAuthTestUtils::build_request('POST', 'http://example.com'); + $this->assertEquals('Authorization: OAuth', OAuthRequest::from_request()->to_header()); + $this->assertEquals('Authorization: OAuth realm="test"', OAuthRequest::from_request()->to_header('test')); + + OAuthTestUtils::build_request('POST', 'http://example.com', 'foo=bar'); + $this->assertEquals('Authorization: OAuth', OAuthRequest::from_request()->to_header()); + $this->assertEquals('Authorization: OAuth realm="test"', OAuthRequest::from_request()->to_header('test')); + + // Is headers supposted to be Urlencoded. More to the point: + // Should it be baz = bla,rgh or baz = bla%2Crgh ?? + // - morten.fangel + OAuthTestUtils::build_request('POST', 'http://example.com', '', 'OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"'); + $this->assertEquals('Authorization: OAuth,oauth_foo="bar",oauth_baz="bla%2Crgh"', OAuthRequest::from_request()->to_header()); + $this->assertEquals('Authorization: OAuth realm="test",oauth_foo="bar",oauth_baz="bla%2Crgh"', OAuthRequest::from_request()->to_header('test')); + } + + public function testWontBuildHeaderWithArrayInput() { + $this->setExpectedException('OAuthException'); + OAuthTestUtils::build_request('POST', 'http://example.com', 'oauth_foo=bar&oauth_foo=baz'); + OAuthRequest::from_request()->to_header(); + } + + public function testBuildBaseString() { + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'n=v'); + $this->assertEquals('POST&http%3A%2F%2Ftestbed%2Ftest&n%3Dv', OAuthRequest::from_request()->get_signature_base_string()); + + OAuthTestUtils::build_request('POST', 'http://testbed/test', 'n=v&n=v2'); + $this->assertEquals('POST&http%3A%2F%2Ftestbed%2Ftest&n%3Dv%26n%3Dv2', OAuthRequest::from_request()->get_signature_base_string()); + + OAuthTestUtils::build_request('GET', 'http://example.com?n=v'); + $this->assertEquals('GET&http%3A%2F%2Fexample.com&n%3Dv', OAuthRequest::from_request()->get_signature_base_string()); + + $params = 'oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_timestamp=1191242090'; + $params .= '&oauth_nonce=hsu94j3884jdopsl&oauth_signature_method=PLAINTEXT&oauth_signature=ignored'; + OAuthTestUtils::build_request('POST', 'https://photos.example.net/request_token', $params); + $this->assertEquals('POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_' + .'consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884j' + .'dopsl%26oauth_signature_method%3DPLAINTEXT%26oauth_timestam' + .'p%3D1191242090%26oauth_version%3D1.0', + OAuthRequest::from_request()->get_signature_base_string()); + + $params = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03'; + $params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh'; + $params .= '&oauth_signature=ignored&oauth_signature_method=HMAC-SHA1'; + OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params); + $this->assertEquals('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation' + .'.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%' + .'3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26o' + .'auth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jd' + .'k%26oauth_version%3D1.0%26size%3Doriginal', + OAuthRequest::from_request()->get_signature_base_string()); + } + + public function testBuildSignature() { + $params = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03'; + $params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh'; + $params .= '&oauth_signature=ignored&oauth_signature_method=HMAC-SHA1'; + OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params); + $r = OAuthRequest::from_request(); + + $cons = new OAuthConsumer('key', 'kd94hf93k423kf44'); + $token = new OAuthToken('token', 'pfkkdhi9sl3r4s00'); + + $hmac = new OAuthSignatureMethod_HMAC_SHA1(); + $plaintext = new OAuthSignatureMethod_PLAINTEXT(); + + $this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $r->build_signature($hmac, $cons, $token)); + $this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $r->build_signature($plaintext, $cons, $token)); + } + + public function testSign() { + $params = 'file=vacation.jpg&size=original&oauth_version=1.0&oauth_consumer_key=dpf43f3p2l4k3l03'; + $params .= '&oauth_token=nnch734d00sl2jdk&oauth_timestamp=1191242096&oauth_nonce=kllo9940pd9333jh'; + $params .= '&oauth_signature=__ignored__&oauth_signature_method=HMAC-SHA1'; + OAuthTestUtils::build_request('GET', 'http://photos.example.net/photos?'.$params); + $r = OAuthRequest::from_request(); + + $cons = new OAuthConsumer('key', 'kd94hf93k423kf44'); + $token = new OAuthToken('token', 'pfkkdhi9sl3r4s00'); + + $hmac = new OAuthSignatureMethod_HMAC_SHA1(); + $plaintext = new OAuthSignatureMethod_PLAINTEXT(); + + // We need to test both what the parameter is, and how the serialized request is.. + + $r->sign_request($hmac, $cons, $token); + $this->assertEquals('HMAC-SHA1', $r->get_parameter('oauth_signature_method')); + $this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $r->get_parameter('oauth_signature')); + $expectedPostdata = 'file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&' + . 'oauth_signature=tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D&oauth_signature_method=HMAC-SHA1&' + . 'oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth_version=1.0&size=original'; + $this->assertEquals( $expectedPostdata, $r->to_postdata()); + + $r->sign_request($plaintext, $cons, $token); + $this->assertEquals('PLAINTEXT', $r->get_parameter('oauth_signature_method')); + $this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $r->get_parameter('oauth_signature')); + $expectedPostdata = 'file=vacation.jpg&oauth_consumer_key=dpf43f3p2l4k3l03&oauth_nonce=kllo9940pd9333jh&' + . 'oauth_signature=kd94hf93k423kf44%26pfkkdhi9sl3r4s00&oauth_signature_method=PLAINTEXT&' + . 'oauth_timestamp=1191242096&oauth_token=nnch734d00sl2jdk&oauth_version=1.0&size=original'; + $this->assertEquals( $expectedPostdata, $r->to_postdata()); + + } +} + +?> \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthServerTest.php b/pacotes/linkedinoauth/tests/OAuthServerTest.php new file mode 100644 index 0000000..d4d1192 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthServerTest.php @@ -0,0 +1,225 @@ +consumer = new OAuthConsumer('key', 'secret'); + $this->request_token = new OAuthToken('requestkey', 'requestsecret'); + $this->access_token = new OAuthToken('accesskey', 'accesssecret'); + + $this->hmac_sha1 = new OAuthSignatureMethod_HMAC_SHA1(); + $this->plaintext = new OAuthSignatureMethod_PLAINTEXT(); + + $this->server = new OAuthServer( new Mock_OAuthDataStore() ); + $this->server->add_signature_method( $this->hmac_sha1 ); + $this->server->add_signature_method( $this->plaintext ); + } + + public function testAcceptValidRequest() { + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + list($consumer, $token) = $this->server->verify_request( $request ); + $this->assertEquals( $this->consumer, $consumer ); + $this->assertEquals( $this->access_token, $token ); + + $request->sign_request( $this->hmac_sha1, $this->consumer, $this->access_token ); + list($consumer, $token) = $this->server->verify_request( $request ); + $this->assertEquals( $this->consumer, $consumer ); + $this->assertEquals( $this->access_token, $token ); + } + + public function testAcceptRequestWithoutVersion() { + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->unset_parameter('oauth_version'); + $request->sign_request( $this->hmac_sha1, $this->consumer, $this->access_token ); + + $this->server->verify_request( $request ); + } + + public function testRejectRequestSignedWithRequestToken() { + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->request_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request( $request ); + } + + public function testRejectRequestWithMissingParameters() { + // The list of required parameters is taken from + // Chapter 7 ("Accessing Protected Resources") + + $required_parameters = array( + 'oauth_consumer_key', + 'oauth_token', + 'oauth_signature_method', + 'oauth_signature', + 'oauth_timestamp', + 'oauth_nonce' + ); + + foreach( $required_parameters AS $required ) { + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + try { + $request->unset_parameter( $required ); + $this->server->verify_request($request); + $this->fail('Allowed a request without `' . $required . '`'); + } catch( OAuthException $e ) { /* expected */ } + } + } + + public function testRejectPastTimestamp() { + // We change the timestamp to be 10 hours ago, it should throw an exception + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->set_parameter( 'oauth_timestamp', $request->get_parameter('oauth_timestamp') - 10*60*60, false); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request($request); + } + + public function testRejectFutureTimestamp() { + // We change the timestamp to be 10 hours in the future, it should throw an exception + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->set_parameter( 'oauth_timestamp', $request->get_parameter('oauth_timestamp') + 10*60*60, false); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request($request); + } + + public function testRejectUsedNonce() { + // We give a known nonce and should see an exception + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + // The Mock datastore is set to say that the `nonce` nonce is known + $request->set_parameter( 'oauth_nonce', 'nonce', false); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request($request); + } + + public function testRejectInvalidSignature() { + // We change the signature post-signing to be something invalid + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + $request->set_parameter( 'oauth_signature', '__whatever__', false); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request($request); + } + + public function testRejectInvalidConsumer() { + // We use the consumer-key "unknown", which isn't known by the datastore. + + $unknown_consumer = new OAuthConsumer('unknown', '__unused__'); + + $request = OAuthRequest::from_consumer_and_token( $unknown_consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $unknown_consumer, $this->access_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request( $request ); + } + + public function testRejectInvalidToken() { + // We use the access-token "unknown" which isn't known by the datastore + + $unknown_token = new OAuthToken('unknown', '__unused__'); + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $unknown_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $unknown_token ); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request( $request ); + } + + public function testRejectUnknownSignatureMethod() { + // We use a server that only supports HMAC-SHA1, but requests with PLAINTEXT signature + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + + $server = new OAuthServer( new Mock_OAuthDataStore() ); + $server->add_signature_method( $this->hmac_sha1 ); + + $this->setExpectedException('OAuthException'); + $server->verify_request( $request ); + } + + public function testRejectUnknownVersion() { + // We use the version "1.0a" which isn't "1.0", so reject the request + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + $request->set_parameter('oauth_version', '1.0a', false); + + $this->setExpectedException('OAuthException'); + $this->server->verify_request( $request ); + } + + public function testCreateRequestToken() { + // We request a new Request Token + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, NULL, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, NULL ); + + $token = $this->server->fetch_request_token($request); + $this->assertEquals($this->request_token, $token); + } + + public function testRejectSignedRequestTokenRequest() { + // We request a new Request Token, but the request is signed with a token which should fail + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->request_token ); + + $this->setExpectedException('OAuthException'); + $token = $this->server->fetch_request_token($request); + } + + public function testCreateAccessToken() { + // We request a new Access Token + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->request_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->request_token ); + + $token = $this->server->fetch_access_token($request); + $this->assertEquals($this->access_token, $token); + } + + public function testRejectUnsignedAccessTokenRequest() { + // We request a new Access Token, but we didn't sign the request with a Access Token + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, NULL, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, NULL ); + + $this->setExpectedException('OAuthException'); + $token = $this->server->fetch_access_token($request); + } + + public function testRejectAccessTokenSignedAccessTokenRequest() { + // We request a new Access Token, but the request is signed with an access token, so fail! + + $request = OAuthRequest::from_consumer_and_token( $this->consumer, $this->access_token, 'POST', 'http://example.com'); + $request->sign_request( $this->plaintext, $this->consumer, $this->access_token ); + + $this->setExpectedException('OAuthException'); + $token = $this->server->fetch_access_token($request); + } +} diff --git a/pacotes/linkedinoauth/tests/OAuthSignatureMethodHmacSha1Test.php b/pacotes/linkedinoauth/tests/OAuthSignatureMethodHmacSha1Test.php new file mode 100644 index 0000000..3d5cc75 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthSignatureMethodHmacSha1Test.php @@ -0,0 +1,60 @@ +method = new OAuthSignatureMethod_HMAC_SHA1(); + } + + public function testIdentifyAsHmacSha1() { + $this->assertEquals('HMAC-SHA1', $this->method->get_name()); + } + + public function testBuildSignature() { + // Tests taken from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1") + $request = new Mock_OAuthBaseStringRequest('bs'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = NULL; + $this->assertEquals('egQqG5AJep5sJ7anhXju1unge2I=', $this->method->build_signature( $request, $consumer, $token) ); + + $request = new Mock_OAuthBaseStringRequest('bs'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = new OAuthToken('__unused__', 'ts'); + $this->assertEquals('VZVjXceV7JgPq/dOTnNmEfO0Fv8=', $this->method->build_signature( $request, $consumer, $token) ); + + $request = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26' + . 'oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26' + . 'oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); + $consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44'); + $token = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00'); + $this->assertEquals('tR3+Ty81lMeYAr/Fid0kMTYa/WM=', $this->method->build_signature( $request, $consumer, $token) ); + } + + public function testVerifySignature() { + // Tests taken from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1") + $request = new Mock_OAuthBaseStringRequest('bs'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = NULL; + $signature = 'egQqG5AJep5sJ7anhXju1unge2I='; + $this->assertTrue( $this->method->check_signature( $request, $consumer, $token, $signature) ); + + $request = new Mock_OAuthBaseStringRequest('bs'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = new OAuthToken('__unused__', 'ts'); + $signature = 'VZVjXceV7JgPq/dOTnNmEfO0Fv8='; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + + $request = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26' + . 'oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26' + . 'oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal'); + $consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44'); + $token = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00'); + $signature = 'tR3+Ty81lMeYAr/Fid0kMTYa/WM='; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthSignatureMethodPlaintextTest.php b/pacotes/linkedinoauth/tests/OAuthSignatureMethodPlaintextTest.php new file mode 100644 index 0000000..d096243 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthSignatureMethodPlaintextTest.php @@ -0,0 +1,79 @@ +method = new OAuthSignatureMethod_PLAINTEXT(); + } + + public function testIdentifyAsPlaintext() { + $this->assertEquals('PLAINTEXT', $this->method->get_name()); + } + + public function testBuildSignature() { + // Tests based on from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1") + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = NULL; + $this->assertEquals('cs&', $this->method->build_signature( $request, $consumer, $token) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = new OAuthToken('__unused__', 'ts'); + $this->assertEquals('cs&ts', $this->method->build_signature( $request, $consumer, $token) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44'); + $token = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00'); + $this->assertEquals('kd94hf93k423kf44&pfkkdhi9sl3r4s00', $this->method->build_signature( $request, $consumer, $token) ); + + // Tests taken from Chapter 9.4.1 ("Generating Signature") from the spec + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88'); + $token = new OAuthToken('__unused__', 'jjd999tj88uiths3'); + $this->assertEquals('djr9rjt0jd78jf88&jjd999tj88uiths3', $this->method->build_signature( $request, $consumer, $token) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88'); + $token = new OAuthToken('__unused__', 'jjd99$tj88uiths3'); + $this->assertEquals('djr9rjt0jd78jf88&jjd99%24tj88uiths3', $this->method->build_signature( $request, $consumer, $token) ); + } + + public function testVerifySignature() { + // Tests based on from http://wiki.oauth.net/TestCases section 9.2 ("HMAC-SHA1") + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = NULL; + $signature = 'cs&'; + $this->assertTrue( $this->method->check_signature( $request, $consumer, $token, $signature) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'cs'); + $token = new OAuthToken('__unused__', 'ts'); + $signature = 'cs&ts'; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'kd94hf93k423kf44'); + $token = new OAuthToken('__unused__', 'pfkkdhi9sl3r4s00'); + $signature = 'kd94hf93k423kf44&pfkkdhi9sl3r4s00'; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + + // Tests taken from Chapter 9.4.1 ("Generating Signature") from the spec + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88'); + $token = new OAuthToken('__unused__', 'jjd999tj88uiths3'); + $signature = 'djr9rjt0jd78jf88&jjd999tj88uiths3'; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + + $request = new Mock_OAuthBaseStringRequest('__unused__'); + $consumer = new OAuthConsumer('__unused__', 'djr9rjt0jd78jf88'); + $token = new OAuthToken('__unused__', 'jjd99$tj88uiths3'); + $signature = 'djr9rjt0jd78jf88&jjd99%24tj88uiths3'; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthSignatureMethodRsaSha1Test.php b/pacotes/linkedinoauth/tests/OAuthSignatureMethodRsaSha1Test.php new file mode 100644 index 0000000..74e5037 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthSignatureMethodRsaSha1Test.php @@ -0,0 +1,43 @@ +method = new Mock_OAuthSignatureMethod_RSA_SHA1(); + } + + public function testIdentifyAsRsaSha1() { + $this->assertEquals('RSA-SHA1', $this->method->get_name()); + } + + public function testBuildSignature() { + if( ! function_exists('openssl_get_privatekey') ) { + $this->markTestSkipped('OpenSSL not available, can\'t test RSA-SHA1 functionality'); + } + + // Tests taken from http://wiki.oauth.net/TestCases section 9.3 ("RSA-SHA1") + $request = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal'); + $consumer = new OAuthConsumer('dpf43f3p2l4k3l03', '__unused__'); + $token = NULL; + $signature = 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE='; + $this->assertEquals($signature, $this->method->build_signature( $request, $consumer, $token) ); + } + + public function testVerifySignature() { + if( ! function_exists('openssl_get_privatekey') ) { + $this->markTestSkipped('OpenSSL not available, can\'t test RSA-SHA1 functionality'); + } + + // Tests taken from http://wiki.oauth.net/TestCases section 9.3 ("RSA-SHA1") + $request = new Mock_OAuthBaseStringRequest('GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal'); + $consumer = new OAuthConsumer('dpf43f3p2l4k3l03', '__unused__'); + $token = NULL; + $signature = 'jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE='; + $this->assertTrue($this->method->check_signature( $request, $consumer, $token, $signature) ); + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthTokenTest.php b/pacotes/linkedinoauth/tests/OAuthTokenTest.php new file mode 100644 index 0000000..20d8113 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthTokenTest.php @@ -0,0 +1,20 @@ +assertEquals('oauth_token=token&oauth_token_secret=secret', $token->to_string()); + + $token = new OAuthToken('token&', 'secret%'); + $this->assertEquals('oauth_token=token%26&oauth_token_secret=secret%25', $token->to_string()); + } + public function testConvertToString() { + $token = new OAuthToken('token', 'secret'); + $this->assertEquals('oauth_token=token&oauth_token_secret=secret', (string) $token); + + $token = new OAuthToken('token&', 'secret%'); + $this->assertEquals('oauth_token=token%26&oauth_token_secret=secret%25', (string) $token); + } +} \ No newline at end of file diff --git a/pacotes/linkedinoauth/tests/OAuthUtilTest.php b/pacotes/linkedinoauth/tests/OAuthUtilTest.php new file mode 100644 index 0000000..a398880 --- /dev/null +++ b/pacotes/linkedinoauth/tests/OAuthUtilTest.php @@ -0,0 +1,133 @@ +assertEquals('abcABC123', OAuthUtil::urlencode_rfc3986('abcABC123')); + $this->assertEquals('-._~', OAuthUtil::urlencode_rfc3986('-._~')); + $this->assertEquals('%25', OAuthUtil::urlencode_rfc3986('%')); + $this->assertEquals('%2B', OAuthUtil::urlencode_rfc3986('+')); + $this->assertEquals('%0A', OAuthUtil::urlencode_rfc3986("\n")); + $this->assertEquals('%20', OAuthUtil::urlencode_rfc3986(' ')); + $this->assertEquals('%7F', OAuthUtil::urlencode_rfc3986("\x7F")); + //$this->assertEquals('%C2%80', OAuthUtil::urlencode_rfc3986("\x00\x80")); + //$this->assertEquals('%E3%80%81', OAuthUtil::urlencode_rfc3986("\x30\x01")); + + // Last two checks disabled because of lack of UTF-8 support, or lack + // of knowledge from me (morten.fangel) on how to use it properly.. + + // A few tests to ensure code-coverage + $this->assertEquals( '', OAuthUtil::urlencode_rfc3986(NULL)); + $this->assertEquals( '', OAuthUtil::urlencode_rfc3986(new stdClass())); + } + + public function testUrldecode() { + // Tests taken from + // http://wiki.oauth.net/TestCases ("Parameter Encoding") + $this->assertEquals('abcABC123', OAuthUtil::urldecode_rfc3986('abcABC123')); + $this->assertEquals('-._~', OAuthUtil::urldecode_rfc3986('-._~')); + $this->assertEquals('%', OAuthUtil::urldecode_rfc3986('%25')); + $this->assertEquals('+', OAuthUtil::urldecode_rfc3986('%2B')); + $this->assertEquals("\n", OAuthUtil::urldecode_rfc3986('%0A')); + $this->assertEquals(' ', OAuthUtil::urldecode_rfc3986('%20')); + $this->assertEquals("\x7F", OAuthUtil::urldecode_rfc3986('%7F')); + //$this->assertEquals("\x00\x80", OAuthUtil::urldecode_rfc3986('%C2%80')); + //$this->assertEquals("\x30\x01", OAuthUtil::urldecode_rfc3986('%E3%80%81')); + + // Last two checks disabled because of lack of UTF-8 support, or lack + // of knowledge from me (morten.fangel) on how to use it properly.. + } + + public function testParseParameter() { + // Tests taken from + // http://wiki.oauth.net/TestCases ("Normalize Request Parameters") + + $this->assertEquals( + array('name'=>''), + OAuthUtil::parse_parameters('name') + ); + $this->assertEquals( + array('a'=>'b'), + OAuthUtil::parse_parameters('a=b') + ); + $this->assertEquals( + array('a'=>'b','c'=>'d'), + OAuthUtil::parse_parameters('a=b&c=d') + ); + $this->assertEquals( + array('a'=>array('x!y','x y')), + OAuthUtil::parse_parameters('a=x!y&a=x+y') + ); + $this->assertEquals( + array('x!y'=>'a', 'x' =>'a'), + OAuthUtil::parse_parameters('x!y=a&x=a') + ); + } + + public function testBuildHttpQuery() { + // Tests taken from + // http://wiki.oauth.net/TestCases ("Normalize Request Parameters") + $this->assertEquals( + 'name=', + OAuthUtil::build_http_query(array('name'=>'')) + ); + $this->assertEquals( + 'a=b', + OAuthUtil::build_http_query(array('a'=>'b')) + ); + $this->assertEquals( + 'a=b&c=d', + OAuthUtil::build_http_query(array('a'=>'b','c'=>'d')) + ); + $this->assertEquals( + 'a=x%20y&a=x%21y', + OAuthUtil::build_http_query(array('a'=>array('x!y','x y'))) + ); + $this->assertEquals( + 'x=a&x%21y=a', + OAuthUtil::build_http_query(array('x!y'=>'a', 'x' =>'a')) + ); + + // Test taken from the Spec 9.1.1 + $this->assertEquals( + 'a=1&c=hi%20there&f=25&f=50&f=a&z=p&z=t', + OAuthUtil::build_http_query(array('a'=>'1', 'c' =>'hi there', 'f'=>array(25, 50, 'a'), 'z'=>array('p','t'))) + ); + } + + public function testSplitHeader() { + $this->assertEquals( + array('oauth_foo'=>'bar','oauth_baz'=>'bla,rgh'), + OAuthUtil::split_header('OAuth realm="",oauth_foo=bar,oauth_baz="bla,rgh"') + ); + $this->assertEquals( + array(), + OAuthUtil::split_header('OAuth realm="",foo=bar,baz="bla,rgh"') + ); + $this->assertEquals( + array('foo'=>'bar', 'baz'=>'bla,rgh'), + OAuthUtil::split_header('OAuth realm="",foo=bar,baz="bla,rgh"', false) + ); + $this->assertEquals( + array('oauth_foo' => 'hi there'), + OAuthUtil::split_header('OAuth realm="",oauth_foo=hi+there,foo=bar,baz="bla,rgh"') + ); + + } + + public function testGetHeaders() { + if (function_exists('apache_request_headers')) { + $this->markTestSkipped('We assume the apache module is well tested. Since this module is present, no need testing our suplement'); + } + + $_SERVER['HTTP_HOST'] = 'foo'; + $_SERVER['HTTP_X_WHATEVER'] = 'bar'; + $this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar'), OAuthUtil::get_headers() ); + } +} diff --git a/pacotes/linkedinoauth/tests/common.php b/pacotes/linkedinoauth/tests/common.php new file mode 100644 index 0000000..89599bc --- /dev/null +++ b/pacotes/linkedinoauth/tests/common.php @@ -0,0 +1,62 @@ +mode) { + if(isset($_GET['login'])) { + $openid->identity = 'https://www.google.com/accounts/o8/id'; + header('Location: ' . $openid->authUrl()); + } +?> + + +
+mode == 'cancel') { + echo 'User has canceled authentication!'; + } else { + echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.'; + } +} catch(ErrorException $e) { + echo $e->getMessage(); +} diff --git a/pacotes/openid/login.php b/pacotes/openid/login.php new file mode 100644 index 0000000..14678b5 --- /dev/null +++ b/pacotes/openid/login.php @@ -0,0 +1,132 @@ + + +Ocorreu algum erro

"; + } + +} +require 'openid.php'; +try { + $openid = new LightOpenID; + if(!$openid->mode && $_SESSION["openid"] == false) { + if(isset($dadosurl['openid_identifier']) && empty($dadosurl["erro"])) { + $openid->identity = $dadosurl['openid_identifier']; + header('Location: ' . $openid->authUrl()); + } +?> + + +
+  +
+ +Utilize uma das redes abaixo para confirmar sua identidade

+  + ';} +?> +  + ';} +?> + ';} +?> +  +  +  +
+ + +mode == 'cancel') { + echo 'User has canceled authentication!'; + } else { + if($_SESSION["openidservico"] != "twitter" && $_SESSION["openidservico"] != "facebook" && $_SESSION["openidservico"] != "linkedin"){ + $valido = $openid->validate(); + $_SESSION["openid"] = false; + if($valido){ + $_SESSION["openid"] = true; + $_SESSION["openidurl"] = $dadosurl["openid_identifier"]; + $_SESSION["openidusuario"] = $dadosurl["usuario"]; + $_SESSION["openidservico"] = $dadosurl["servico"]; + $_SESSION["openidimagem"] = $dadosurl["imagem"]; + $_SESSION["openidnome"] = $dadosurl["nome"]; + } + } + else{ + $valido = $_SESSION["openid"]; + } + if($valido){ + header('Location: ' . $_SESSION["urlVolta"]); + } + if(!$valido){ + $url = "login.php?login&erro=ok"; + header('Location: ' . $url); + } + } +} catch(ErrorException $e) { + echo $e->getMessage(); +} +?> \ No newline at end of file diff --git a/pacotes/openid/openid.php b/pacotes/openid/openid.php new file mode 100644 index 0000000..e71069a --- /dev/null +++ b/pacotes/openid/openid.php @@ -0,0 +1,743 @@ + + * $openid = new LightOpenID; + * $openid->identity = 'ID supplied by user'; + * header('Location: ' . $openid->authUrl()); + * + * The provider then sends various parameters via GET, one of them is openid_mode. + * Step two is verification: + * + * if ($this->data['openid_mode']) { + * $openid = new LightOpenID; + * echo $openid->validate() ? 'Logged in.' : 'Failed'; + * } + * + * + * Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an alias). + * The default values for those are: + * $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; + * $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI']; + * If you don't know their meaning, refer to any openid tutorial, or specification. Or just guess. + * + * AX and SREG extensions are supported. + * To use them, specify $openid->required and/or $openid->optional before calling $openid->authUrl(). + * These are arrays, with values being AX schema paths (the 'path' part of the URL). + * For example: + * $openid->required = array('namePerson/friendly', 'contact/email'); + * $openid->optional = array('namePerson/first'); + * If the server supports only SREG or OpenID 1.1, these are automaticaly + * mapped to SREG names, so that user doesn't have to know anything about the server. + * + * To get the values, use $openid->getAttributes(). + * + * + * The library requires PHP >= 5.1.2 with curl or http/https stream wrappers enabled.. + * @author Mewp + * @copyright Copyright (c) 2010, Mewp + * @license http://www.opensource.org/licenses/mit-license.php MIT + */ +class LightOpenID +{ + public $returnUrl + , $g_sid + , $required = array() + , $optional = array() + , $verify_peer = null + , $capath = null + , $cainfo = null; + private $identity, $claimed_id; + protected $server, $version, $trustRoot, $aliases, $identifier_select = false + , $ax = false, $sreg = false, $data; + static protected $ax_to_sreg = array( + 'namePerson/friendly' => 'nickname', + 'contact/email' => 'email', + 'namePerson' => 'fullname', + 'birthDate' => 'dob', + 'person/gender' => 'gender', + 'contact/postalCode/home' => 'postcode', + 'contact/country/home' => 'country', + 'pref/language' => 'language', + 'pref/timezone' => 'timezone', + ); + + function __construct() + { + $this->trustRoot = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; + $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?'); + $this->returnUrl = $this->trustRoot . $uri; + + $this->data = $_POST + $_GET; # OPs may send data as POST or GET. + } + + function __set($name, $value) + { + switch ($name) { + case 'identity': + if (strlen($value = trim((String) $value))) { + if (preg_match('#^xri:/*#i', $value, $m)) { + $value = substr($value, strlen($m[0])); + } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) { + $value = "http://$value"; + } + if (preg_match('#^https?://[^/]+$#i', $value, $m)) { + $value .= '/'; + } + } + $this->$name = $this->claimed_id = $value; + break; + case 'trustRoot': + case 'realm': + $this->trustRoot = trim($value); + } + } + + function __get($name) + { + switch ($name) { + case 'identity': + # We return claimed_id instead of identity, + # because the developer should see the claimed identifier, + # i.e. what he set as identity, not the op-local identifier (which is what we verify) + return $this->claimed_id; + case 'trustRoot': + case 'realm': + return $this->trustRoot; + case 'mode': + return empty($this->data['openid_mode']) ? null : $this->data['openid_mode']; + } + } + + /** + * Checks if the server specified in the url exists. + * + * @param $url url to check + * @return true, if the server exists; false otherwise + */ + function hostExists($url) + { + if (strpos($url, '/') === false) { + $server = $url; + } else { + $server = @parse_url($url, PHP_URL_HOST); + } + + if (!$server) { + return false; + } + + return !!gethostbynamel($server); + } + + protected function request_curl($url, $method='GET', $params=array()) + { + $s = PHP_SHLIB_SUFFIX; + if(!function_exists('curl_init')) + {@dl( 'php_curl'.'.'.$s );} + if(!function_exists('curl_init')) + {echo "curl no instalado";} + $params = http_build_query($params, '', '&'); + $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : '')); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*')); + + if($this->verify_peer !== null) { + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer); + if($this->capath) { + curl_setopt($curl, CURLOPT_CAPATH, $this->capath); + } + + if($this->cainfo) { + curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo); + } + } + + if ($method == 'POST') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $params); + } elseif ($method == 'HEAD') { + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_NOBODY, true); + } else { + curl_setopt($curl, CURLOPT_HTTPGET, true); + } + $response = curl_exec($curl); + if($method == 'HEAD') { + $headers = array(); + foreach(explode("\n", $response) as $header) { + $pos = strpos($header,':'); + $name = strtolower(trim(substr($header, 0, $pos))); + $headers[$name] = trim(substr($header, $pos+1)); + } + + # Updating claimed_id in case of redirections. + $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL); + if($effective_url != $url) { + $this->identity = $this->claimed_id = $effective_url; + } + + return $headers; + } + + if (curl_errno($curl)) { + throw new ErrorException(curl_error($curl), curl_errno($curl)); + } + return $response; + } + + protected function request_streams($url, $method='GET', $params=array()) + { + if(!$this->hostExists($url)) { + throw new ErrorException('Invalid request.'); + } + + $params = http_build_query($params, '', '&'); + switch($method) { + case 'GET': + $opts = array( + 'http' => array( + 'method' => 'GET', + 'header' => 'Accept: application/xrds+xml, */*', + 'ignore_errors' => true, + ) + ); + $url = $url . ($params ? '?' . $params : ''); + break; + case 'POST': + $opts = array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Content-type: application/x-www-form-urlencoded', + 'content' => $params, + 'ignore_errors' => true, + ) + ); + break; + case 'HEAD': + # We want to send a HEAD request, + # but since get_headers doesn't accept $context parameter, + # we have to change the defaults. + $default = stream_context_get_options(stream_context_get_default()); + stream_context_get_default( + array('http' => array( + 'method' => 'HEAD', + 'header' => 'Accept: application/xrds+xml, */*', + 'ignore_errors' => true, + )) + ); + + $url = $url . ($params ? '?' . $params : ''); + $headers_tmp = get_headers ($url); + if(!$headers_tmp) { + return array(); + } + + # Parsing headers. + $headers = array(); + foreach($headers_tmp as $header) { + $pos = strpos($header,':'); + $name = strtolower(trim(substr($header, 0, $pos))); + $headers[$name] = trim(substr($header, $pos+1)); + + # Following possible redirections. The point is just to have + # claimed_id change with them, because get_headers() will + # follow redirections automatically. + # We ignore redirections with relative paths. + # If any known provider uses them, file a bug report. + if($name == 'location') { + if(strpos($headers[$name], 'http') === 0) { + $this->identity = $this->claimed_id = $headers[$name]; + } elseif($headers[$name][0] == '/') { + $parsed_url = parse_url($this->claimed_id); + $this->identity = + $this->claimed_id = $parsed_url['scheme'] . '://' + . $parsed_url['host'] + . $headers[$name]; + } + } + } + + # And restore them. + stream_context_get_default($default); + //var_dump($headers);exit; + return $headers; + } + + if($this->verify_peer) { + $opts += array('ssl' => array( + 'verify_peer' => true, + 'capath' => $this->capath, + 'cafile' => $this->cainfo, + )); + } + + $context = stream_context_create ($opts); + + return file_get_contents($url, false, $context); + } + + protected function request($url, $method='GET', $params=array()) + { + if(function_exists('curl_init') && !ini_get('safe_mode')) { + return $this->request_curl($url, $method, $params); + } + return $this->request_streams($url, $method, $params); + } + + protected function build_url($url, $parts) + { + if (isset($url['query'], $parts['query'])) { + $parts['query'] = $url['query'] . '&' . $parts['query']; + } + + $url = $parts + $url; + $url = $url['scheme'] . '://' + . (empty($url['username'])?'' + :(empty($url['password'])? "{$url['username']}@" + :"{$url['username']}:{$url['password']}@")) + . $url['host'] + . (empty($url['port'])?'':":{$url['port']}") + . (empty($url['path'])?'':$url['path']) + . (empty($url['query'])?'':"?{$url['query']}") + . (empty($url['fragment'])?'':"#{$url['fragment']}"); + return $url; + } + + /** + * Helper function used to scan for / tags and extract information + * from them + */ + protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName) + { + preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1); + preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2); + + $result = array_merge($matches1[1], $matches2[1]); + return empty($result)?false:$result[0]; + } + + /** + * Performs Yadis and HTML discovery. Normally not used. + * @param $url Identity URL. + * @return String OP Endpoint (i.e. OpenID provider address). + * @throws ErrorException + */ + function discover($url) + { + if (!$url) throw new ErrorException('No identity supplied.'); + # Use xri.net proxy to resolve i-name identities + if (!preg_match('#^https?:#', $url)) { + $url = "https://xri.net/$url"; + } + + # We save the original url in case of Yadis discovery failure. + # It can happen when we'll be lead to an XRDS document + # which does not have any OpenID2 services. + $originalUrl = $url; + + # A flag to disable yadis discovery in case of failure in headers. + $yadis = true; + + # We'll jump a maximum of 5 times, to avoid endless redirections. + for ($i = 0; $i < 5; $i ++) { + if ($yadis) { + $headers = $this->request($url, 'HEAD'); + + $next = false; + if (isset($headers['x-xrds-location'])) { + $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location']))); + $next = true; + } + + if (isset($headers['content-type']) + && (strpos($headers['content-type'], 'application/xrds+xml') !== false + || strpos($headers['content-type'], 'text/xml') !== false) + ) { + # Apparently, some providers return XRDS documents as text/html. + # While it is against the spec, allowing this here shouldn't break + # compatibility with anything. + # --- + # Found an XRDS document, now let's find the server, and optionally delegate. + $content = $this->request($url, 'GET'); + + preg_match_all('#(.*?)#s', $content, $m); + foreach($m[1] as $content) { + $content = ' ' . $content; # The space is added, so that strpos doesn't return 0. + + # OpenID 2 + $ns = preg_quote('http://specs.openid.net/auth/2.0/'); + if(preg_match('#\s*'.$ns.'(server|signon)\s*#s', $content, $type)) { + if ($type[1] == 'server') $this->identifier_select = true; + + preg_match('#(.*)#', $content, $server); + preg_match('#<(Local|Canonical)ID>(.*)#', $content, $delegate); + if (empty($server)) { + return false; + } + # Does the server advertise support for either AX or SREG? + $this->ax = (bool) strpos($content, 'http://openid.net/srv/ax/1.0'); + $this->sreg = strpos($content, 'http://openid.net/sreg/1.0') + || strpos($content, 'http://openid.net/extensions/sreg/1.1'); + + $server = $server[1]; + if (isset($delegate[2])) $this->identity = trim($delegate[2]); + $this->version = 2; + + $this->server = $server; + return $server; + } + + # OpenID 1.1 + $ns = preg_quote('http://openid.net/signon/1.1'); + if (preg_match('#\s*'.$ns.'\s*#s', $content)) { + + preg_match('#(.*)#', $content, $server); + preg_match('#<.*?Delegate>(.*)#', $content, $delegate); + if (empty($server)) { + return false; + } + # AX can be used only with OpenID 2.0, so checking only SREG + $this->sreg = strpos($content, 'http://openid.net/sreg/1.0') + || strpos($content, 'http://openid.net/extensions/sreg/1.1'); + + $server = $server[1]; + if (isset($delegate[1])) $this->identity = $delegate[1]; + $this->version = 1; + + $this->server = $server; + return $server; + } + } + + $next = true; + $yadis = false; + $url = $originalUrl; + $content = null; + break; + } + if ($next) continue; + + # There are no relevant information in headers, so we search the body. + $content = $this->request($url, 'GET'); + $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content'); + if ($location) { + $url = $this->build_url(parse_url($url), parse_url($location)); + continue; + } + } + + if (!$content) $content = $this->request($url, 'GET'); + + # At this point, the YADIS Discovery has failed, so we'll switch + # to openid2 HTML discovery, then fallback to openid 1.1 discovery. + $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href'); + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href'); + $this->version = 2; + + if (!$server) { + # The same with openid 1.1 + $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href'); + $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href'); + $this->version = 1; + } + + if ($server) { + # We found an OpenID2 OP Endpoint + if ($delegate) { + # We have also found an OP-Local ID. + $this->identity = $delegate; + } + $this->server = $server; + return $server; + } + + throw new ErrorException('No servers found!'); + } + throw new ErrorException('Endless redirection!'); + } + + protected function sregParams() + { + $params = array(); + # We always use SREG 1.1, even if the server is advertising only support for 1.0. + # That's because it's fully backwards compatibile with 1.0, and some providers + # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com + $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; + if ($this->required) { + $params['openid.sreg.required'] = array(); + foreach ($this->required as $required) { + if (!isset(self::$ax_to_sreg[$required])) continue; + $params['openid.sreg.required'][] = self::$ax_to_sreg[$required]; + } + $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']); + } + + if ($this->optional) { + $params['openid.sreg.optional'] = array(); + foreach ($this->optional as $optional) { + if (!isset(self::$ax_to_sreg[$optional])) continue; + $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional]; + } + $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']); + } + return $params; + } + + protected function axParams() + { + $params = array(); + if ($this->required || $this->optional) { + $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0'; + $params['openid.ax.mode'] = 'fetch_request'; + $this->aliases = array(); + $counts = array(); + $required = array(); + $optional = array(); + foreach (array('required','optional') as $type) { + foreach ($this->$type as $alias => $field) { + if (is_int($alias)) $alias = strtr($field, '/', '_'); + $this->aliases[$alias] = 'http://axschema.org/' . $field; + if (empty($counts[$alias])) $counts[$alias] = 0; + $counts[$alias] += 1; + ${$type}[] = $alias; + } + } + foreach ($this->aliases as $alias => $ns) { + $params['openid.ax.type.' . $alias] = $ns; + } + foreach ($counts as $alias => $count) { + if ($count == 1) continue; + $params['openid.ax.count.' . $alias] = $count; + } + + # Don't send empty ax.requied and ax.if_available. + # Google and possibly other providers refuse to support ax when one of these is empty. + if($required) { + $params['openid.ax.required'] = implode(',', $required); + } + if($optional) { + $params['openid.ax.if_available'] = implode(',', $optional); + } + } + return $params; + } + + protected function authUrl_v1() + { + $returnUrl = $this->returnUrl; + # If we have an openid.delegate that is different from our claimed id, + # we need to somehow preserve the claimed id between requests. + # The simplest way is to just send it along with the return_to url. + if($this->identity != $this->claimed_id) { + $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id; + } + + $params = array( + 'openid.return_to' => $returnUrl, + 'openid.mode' => 'checkid_setup', + 'openid.identity' => $this->identity, + 'openid.trust_root' => $this->trustRoot, + ) + $this->sregParams(); + + return $this->build_url(parse_url($this->server) + , array('query' => http_build_query($params, '', '&'))); + } + + protected function authUrl_v2($identifier_select) + { + $params = array( + 'openid.ns' => 'http://specs.openid.net/auth/2.0', + 'openid.mode' => 'checkid_setup', + 'openid.return_to' => $this->returnUrl, + 'openid.realm' => $this->trustRoot, + ); + if ($this->ax) { + $params += $this->axParams(); + } + if ($this->sreg) { + $params += $this->sregParams(); + } + if (!$this->ax && !$this->sreg) { + # If OP doesn't advertise either SREG, nor AX, let's send them both + # in worst case we don't get anything in return. + $params += $this->axParams() + $this->sregParams(); + } + + if ($identifier_select) { + $params['openid.identity'] = $params['openid.claimed_id'] + = 'http://specs.openid.net/auth/2.0/identifier_select'; + } else { + $params['openid.identity'] = $this->identity; + $params['openid.claimed_id'] = $this->claimed_id; + } + + return $this->build_url(parse_url($this->server) + , array('query' => http_build_query($params, '', '&'))); + } + + /** + * Returns authentication url. Usually, you want to redirect your user to it. + * @return String The authentication url. + * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1. + * @throws ErrorException + */ + function authUrl($identifier_select = null) + { + if (!$this->server) $this->discover($this->identity); + + if ($this->version == 2) { + if ($identifier_select === null) { + return $this->authUrl_v2($this->identifier_select); + } + return $this->authUrl_v2($identifier_select); + } + return $this->authUrl_v1(); + } + + /** + * Performs OpenID verification with the OP. + * @return Bool Whether the verification was successful. + * @throws ErrorException + */ + function validate() + { + $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity']; + $params = array( + 'openid.assoc_handle' => $this->data['openid_assoc_handle'], + 'openid.signed' => $this->data['openid_signed'], + 'openid.sig' => $this->data['openid_sig'], + ); + + if (isset($this->data['openid_ns'])) { + # We're dealing with an OpenID 2.0 server, so let's set an ns + # Even though we should know location of the endpoint, + # we still need to verify it by discovery, so $server is not set here + $params['openid.ns'] = 'http://specs.openid.net/auth/2.0'; + } elseif (isset($this->data['openid_claimed_id']) + && $this->data['openid_claimed_id'] != $this->data['openid_identity'] + ) { + # If it's an OpenID 1 provider, and we've got claimed_id, + # we have to append it to the returnUrl, like authUrl_v1 does. + $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?') + . 'openid.claimed_id=' . $this->claimed_id; + } + + if ($this->data['openid_return_to'] != $this->returnUrl) { + # The return_to url must match the url of current request. + # I'm assuing that noone will set the returnUrl to something that doesn't make sense. + return false; + } + + $server = $this->discover($this->claimed_id); + + foreach (explode(',', $this->data['openid_signed']) as $item) { + # Checking whether magic_quotes_gpc is turned on, because + # the function may fail if it is. For example, when fetching + # AX namePerson, it might containg an apostrophe, which will be escaped. + # In such case, validation would fail, since we'd send different data than OP + # wants to verify. stripslashes() should solve that problem, but we can't + # use it when magic_quotes is off. + $value = $this->data['openid_' . str_replace('.','_',$item)]; + $params['openid.' . $item] = get_magic_quotes_gpc() ? stripslashes($value) : $value; + + } + + $params['openid.mode'] = 'check_authentication'; + $response = $this->request($server, 'POST', $params); + return preg_match('/is_valid\s*:\s*true/i', $response); + } + + protected function getAxAttributes() + { + $alias = null; + if (isset($this->data['openid_ns_ax']) + && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0' + ) { # It's the most likely case, so we'll check it before + $alias = 'ax'; + } else { + # 'ax' prefix is either undefined, or points to another extension, + # so we search for another prefix + foreach ($this->data as $key => $val) { + if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_' + && $val == 'http://openid.net/srv/ax/1.0' + ) { + $alias = substr($key, strlen('openid_ns_')); + break; + } + } + } + if (!$alias) { + # An alias for AX schema has not been found, + # so there is no AX data in the OP's response + return array(); + } + + $attributes = array(); + foreach ($this->data as $key => $value) { + $keyMatch = 'openid_' . $alias . '_value_'; + if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { + continue; + } + $key = substr($key, strlen($keyMatch)); + if (!isset($this->data['openid_' . $alias . '_type_' . $key])) { + # OP is breaking the spec by returning a field without + # associated ns. This shouldn't happen, but it's better + # to check, than cause an E_NOTICE. + continue; + } + $key = substr($this->data['openid_' . $alias . '_type_' . $key], + strlen('http://axschema.org/')); + $attributes[$key] = $value; + } + return $attributes; + } + + protected function getSregAttributes() + { + $attributes = array(); + $sreg_to_ax = array_flip(self::$ax_to_sreg); + foreach ($this->data as $key => $value) { + $keyMatch = 'openid_sreg_'; + if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { + continue; + } + $key = substr($key, strlen($keyMatch)); + if (!isset($sreg_to_ax[$key])) { + # The field name isn't part of the SREG spec, so we ignore it. + continue; + } + $attributes[$sreg_to_ax[$key]] = $value; + } + return $attributes; + } + + /** + * Gets AX/SREG attributes provided by OP. should be used only after successful validaton. + * Note that it does not guarantee that any of the required/optional parameters will be present, + * or that there will be no other attributes besides those specified. + * In other words. OP may provide whatever information it wants to. + * * SREG names will be mapped to AX names. + * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email' + * @see http://www.axschema.org/types/ + */ + function getAttributes() + { + if (isset($this->data['openid_ns']) + && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0' + ) { # OpenID 2.0 + # We search for both AX and SREG attributes, with AX taking precedence. + return $this->getAxAttributes() + $this->getSregAttributes(); + } + return $this->getSregAttributes(); + } +} diff --git a/pacotes/openid/provider/example-mysql.php b/pacotes/openid/provider/example-mysql.php new file mode 100644 index 0000000..574e3c8 --- /dev/null +++ b/pacotes/openid/provider/example-mysql.php @@ -0,0 +1,194 @@ +dh = false; + * However, the latter one would disable stateful mode, unless connecting via HTTPS. + */ +require 'provider.php'; + +mysql_connect(); +mysql_select_db('test'); + +function getUserData($handle=null) +{ + if(isset($_POST['login'],$_POST['password'])) { + $login = mysql_real_escape_string($_POST['login']); + $password = sha1($_POST['password']); + $q = mysql_query("SELECT * FROM Users WHERE login = '$login' AND password = '$password'"); + if($data = mysql_fetch_assoc($q)) { + return $data; + } + if($handle) { + echo 'Wrong login/password.'; + } + } + if($handle) { + ?> +
+ + Login:
+ Password:
+ +
+ 'First name', + 'namePerson/last' => 'Last name', + 'namePerson/friendly' => 'Nickname (login)' + ); + + private $attrFieldMap = array( + 'namePerson/first' => 'firstName', + 'namePerson/last' => 'lastName', + 'namePerson/friendly' => 'login' + ); + + function setup($identity, $realm, $assoc_handle, $attributes) + { + $data = getUserData($assoc_handle); + echo '
' + . '' + . '' + . '' + . "$realm wishes to authenticate you."; + if($attributes['required'] || $attributes['optional']) { + echo " It also requests following information (required fields marked with *):" + . '
    '; + + foreach($attributes['required'] as $attr) { + if(isset($this->attrMap[$attr])) { + echo '
  • ' + . ' ' + . $this->attrMap[$attr] . '(*)
  • '; + } + } + + foreach($attributes['optional'] as $attr) { + if(isset($this->attrMap[$attr])) { + echo '
  • ' + . ' ' + . $this->attrMap[$attr] . '
  • '; + } + } + echo '
'; + } + echo '
' + . ' ' + . ' ' + . ' ' + . '
'; + } + + function checkid($realm, &$attributes) + { + if(isset($_POST['cancel'])) { + $this->cancel(); + } + + $data = getUserData(); + if(!$data) { + return false; + } + $realm = mysql_real_escape_string($realm); + $q = mysql_query("SELECT attributes FROM AllowedSites WHERE user = '{$data['id']}' AND realm = '$realm'"); + + $attrs = array(); + if($attrs = mysql_fetch_row($q)) { + $attrs = explode(',', $attributes[0]); + } elseif(isset($_POST['attributes'])) { + $attrs = array_keys($_POST['attributes']); + } elseif(!isset($_POST['once']) && !isset($_POST['always'])) { + return false; + } + + $attributes = array(); + foreach($attrs as $attr) { + if(isset($this->attrFieldMap[$attr])) { + $attributes[$attr] = $data[$this->attrFieldMap[$attr]]; + } + } + + if(isset($_POST['always'])) { + $attrs = mysql_real_escape_string(implode(',', array_keys($attributes))); + mysql_query("REPLACE INTO AllowedSites VALUES('{$data['id']}', '$realm', '$attrs')"); + } + + return $this->serverLocation . '?' . $data['login']; + } + + function assoc_handle() + { + # We generate an integer assoc handle, because it's just faster to look up an integer later. + $q = mysql_query("SELECT MAX(id) FROM Associations"); + $result = mysql_fetch_row($q); + return $q[0]+1; + } + + function setAssoc($handle, $data) + { + $data = mysql_real_escape_string(serialize($data)); + mysql_query("REPLACE INTO Associations VALUES('$handle', '$data')"); + } + + function getAssoc($handle) + { + if(!is_numeric($handle)) { + return false; + } + $q = mysql_query("SELECT data FROM Associations WHERE id = '$handle'"); + $data = mysql_fetch_row($q); + if(!$data) { + return false; + } + return unserialize($data[0]); + } + + function delAssoc($handle) + { + if(!is_numeric($handle)) { + return false; + } + mysql_query("DELETE FROM Associations WHERE id = '$handle'"); + } + +} +$op = new MysqlProvider; +$op->server(); diff --git a/pacotes/openid/provider/example.php b/pacotes/openid/provider/example.php new file mode 100644 index 0000000..b8a4c24 --- /dev/null +++ b/pacotes/openid/provider/example.php @@ -0,0 +1,53 @@ +select_id = false; + } + } + + function setup($identity, $realm, $assoc_handle, $attributes) + { + header('WWW-Authenticate: Basic realm="' . $this->data['openid_realm'] . '"'); + header('HTTP/1.0 401 Unauthorized'); + } + + function checkid($realm, &$attributes) + { + if(!isset($_SERVER['PHP_AUTH_USER'])) { + return false; + } + + if ($_SERVER['PHP_AUTH_USER'] == $this->login + && $_SERVER['PHP_AUTH_PW'] == $this->password + ) { + # Returning identity + # It can be any url that leads here, or to any other place that hosts + # an XRDS document pointing here. + return $this->serverLocation . '?id=' . $this->login; + } + + return false; + } + +} +$op = new BasicProvider; +$op->login = 'test'; +$op->password = 'test'; +$op->server(); diff --git a/pacotes/openid/provider/provider.php b/pacotes/openid/provider/provider.php new file mode 100644 index 0000000..b0cacbf --- /dev/null +++ b/pacotes/openid/provider/provider.php @@ -0,0 +1,833 @@ += 5.1.2 + * + * This is an alpha version, using it in production code is not recommended, + * until you are *sure* that it works and is secure. + * + * Please send me messages about your testing results + * (even if successful, so I know that it has been tested). + * Also, if you think there's a way to make it easier to use, tell me -- it's an alpha for a reason. + * Same thing applies to bugs in code, suggestions, + * and everything else you'd like to say about the library. + * + * There's no usage documentation here, see the examples. + * + * @author Mewp + * @copyright Copyright (c) 2010, Mewp + * @license http://www.opensource.org/licenses/mit-license.php MIT + */ +ini_set('error_log','log'); +abstract class LightOpenIDProvider +{ + # URL-s to XRDS and server location. + public $xrdsLocation, $serverLocation; + + # Should we operate in server, or signon mode? + public $select_id = false; + + # Lifetime of an association. + protected $assoc_lifetime = 600; + + # Variables below are either set automatically, or are constant. + # ----- + # Can we support DH? + protected $dh = true; + protected $ns = 'http://specs.openid.net/auth/2.0'; + protected $data, $assoc; + + # Default DH parameters as defined in the specification. + protected $default_modulus; + protected $default_gen = 'Ag=='; + + # AX <-> SREG transform + protected $ax_to_sreg = array( + 'namePerson/friendly' => 'nickname', + 'contact/email' => 'email', + 'namePerson' => 'fullname', + 'birthDate' => 'dob', + 'person/gender' => 'gender', + 'contact/postalCode/home' => 'postcode', + 'contact/country/home' => 'country', + 'pref/language' => 'language', + 'pref/timezone' => 'timezone', + ); + + # Math + private $add, $mul, $pow, $mod, $div, $powmod; + # ----- + + # ------------------------------------------------------------------------ # + # Functions you probably want to implement when extending the class. + + /** + * Checks whether an user is authenticated. + * The function should determine what fields it wants to send to the RP, + * and put them in the $attributes array. + * @param Array $attributes + * @param String $realm Realm used for authentication. + * @return String OP-local identifier of an authenticated user, or an empty value. + */ + abstract function checkid($realm, &$attributes); + + /** + * Displays an user interface for inputting user's login and password. + * Attributes are always AX field namespaces, with stripped host part. + * For example, the $attributes array may be: + * array( 'required' => array('namePerson/friendly', 'contact/email'), + * 'optional' => array('pref/timezone', 'pref/language') + * @param String $identity Discovered identity string. May be used to extract login, unless using $this->select_id + * @param String $realm Realm used for authentication. + * @param String Association handle. must be sent as openid.assoc_handle in $_GET or $_POST in subsequent requests. + * @param Array User attributes requested by the RP. + */ + abstract function setup($identity, $realm, $assoc_handle, $attributes); + + /** + * Stores an association. + * If you want to use php sessions in your provider code, you have to replace it. + * @param String $handle Association handle -- should be used as a key. + * @param Array $assoc Association data. + */ + protected function setAssoc($handle, $assoc) + { + if(session_id()) session_destroy(); + session_id($assoc['handle']); + session_start(); + $_SESSION['assoc'] = $assoc; + session_commit(); + session_id(''); + } + + /** + * Retreives association data. + * If you want to use php sessions in your provider code, you have to replace it. + * @param String $handle Association handle. + * @return Array Association data. + */ + protected function getAssoc($handle) + { + if(session_id()) session_destroy(); + session_id($handle); + session_start(); + if(empty($_SESSION['assoc'])) { + return null; + } + return $_SESSION['assoc']; + session_commit(); + session_id(''); + } + + /** + * Deletes an association. + * If you want to use php sessions in your provider code, you have to replace it. + * @param String $handle Association handle. + */ + protected function delAssoc($handle) + { + if(session_id()) session_destroy(); + session_id($handle); + session_start(); + session_destroy(); + session_id(''); + } + + # ------------------------------------------------------------------------ # + # Functions that you might want to implement. + + /** + * Redirects the user to an url. + * @param String $location The url that the user will be redirected to. + */ + protected function redirect($location) + { + header('Location: ' . $location); + die(); + } + + /** + * Generates a new association handle. + * @return string + */ + protected function assoc_handle() + { + return sha1(microtime()); + } + + /** + * Generates a random shared secret. + * @return string + */ + protected function shared_secret($hash) + { + $length = 20; + if($hash == 'sha256') { + $length = 256; + } + + $secret = ''; + for($i = 0; $i < $length; $i++) { + $secret .= mt_rand(0,255); + } + + return $secret; + } + + /** + * Generates a private key. + * @param int $length Length of the key. + */ + protected function keygen($length) + { + $key = ''; + for($i = 1; $i < $length; $i++) { + $key .= mt_rand(0,9); + } + $key .= mt_rand(1,9); + + return $key; + } + + # ------------------------------------------------------------------------ # + # Functions that you probably shouldn't touch. + + function __construct() + { + $this->default_modulus = + 'ANz5OguIOXLsDhmYmsWizjEOHTdxfo2Vcbt2I3MYZuYe91ouJ4mLBX+YkcLiemOcPy' + . 'm2CBRYHNOyyjmG0mg3BVd9RcLn5S3IHHoXGHblzqdLFEi/368Ygo79JRnxTkXjgmY0' + . 'rxlJ5bU1zIKaSDuKdiI+XUkKJX8Fvf8W8vsixYOr'; + + $location = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' + . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $location = preg_replace('/\?.*/','',$location); + $this->serverLocation = $location; + $location .= (strpos($location, '?') ? '&' : '?') . 'xrds'; + $this->xrdsLocation = $location; + + $this->data = $_GET + $_POST; + + # We choose GMP if avaiable, and bcmath otherwise + if(function_exists('gmp_add')) { + $this->add = 'gmp_add'; + $this->mul = 'gmp_mul'; + $this->pow = 'gmp_pow'; + $this->mod = 'gmp_mod'; + $this->div = 'gmp_div'; + $this->powmod = 'gmp_powm'; + } elseif(function_exists('bcadd')) { + $this->add = 'bcadd'; + $this->mul = 'bcmul'; + $this->pow = 'bcpow'; + $this->mod = 'bcmod'; + $this->div = 'bcdiv'; + $this->powmod = 'bcpowmod'; + } else { + # If neither are avaiable, we can't use DH + $this->dh = false; + } + + # However, we do require the hash functions. + # They should be built-in anyway. + if(!function_exists('hash_algos')) { + $this->dh = false; + } + } + + /** + * Displays an XRDS document, or redirects to it. + * By default, it detects whether it should display or redirect automatically. + * @param bool|null $force When true, always display the document, when false always redirect. + */ + function xrds($force=null) + { + if($force) { + echo $this->xrdsContent(); + die(); + } elseif($force === false) { + header('X-XRDS-Location: '. $this->xrdsLocation); + return; + } + + if (isset($_GET['xrds']) + || (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'application/xrds+xml') !== false) + ) { + header('Content-Type: application/xrds+xml'); + echo $this->xrdsContent(); + die(); + } + + header('X-XRDS-Location: ' . $this->xrdsLocation); + } + + /** + * Returns the content of the XRDS document + * @return String The XRDS document. + */ + protected function xrdsContent() + { + $lines = array( + '', + '', + '', + ' ', + ' ' . $this->ns . '/' . ($this->select_id ? 'server' : 'signon') .'', + ' ' . $this->serverLocation . '', + ' ', + '', + '' + ); + return implode("\n", $lines); + } + + /** + * Does everything that a provider has to -- in one function. + */ + function server() + { + if(isset($this->data['openid_assoc_handle'])) { + $this->assoc = $this->getAssoc($this->data['openid_assoc_handle']); + if(isset($this->assoc['data'])) { + # We have additional data stored for setup. + $this->data += $this->assoc['data']; + unset($this->assoc['data']); + } + } + + if (isset($this->data['openid_ns']) + && $this->data['openid_ns'] == $this->ns + ) { + if(!isset($this->data['openid_mode'])) $this->errorResponse(); + + switch($this->data['openid_mode']) + { + case 'checkid_immediate': + case 'checkid_setup': + $this->checkRealm(); + # We support AX xor SREG. + $attributes = $this->ax(); + if(!$attributes) { + $attributes = $this->sreg(); + } + + # Even if some user is authenticated, we need to know if it's + # the same one that want's to authenticate. + # Of course, if we use select_id, we accept any user. + if (($identity = $this->checkid($this->data['openid_realm'], $attrValues)) + && ($this->select_id || $identity == $this->data['openid_identity']) + ) { + $this->positiveResponse($identity, $attrValues); + } elseif($this->data['openid_mode'] == 'checkid_immediate') { + $this->redirect($this->response(array('openid.mode' => 'setup_needed'))); + } else { + if(!$this->assoc) { + $this->generateAssociation(); + $this->assoc['private'] = true; + } + $this->assoc['data'] = $this->data; + $this->setAssoc($this->assoc['handle'], $this->assoc); + $this->setup($this->data['openid_identity'], + $this->data['openid_realm'], + $this->assoc['handle'], + $attributes); + } + break; + case 'associate': + $this->associate(); + break; + case 'check_authentication': + $this->checkRealm(); + if($this->verify()) { + echo "ns:$this->ns\nis_valid:true"; + if(strpos($this->data['openid_signed'],'invalidate_handle') !== false) { + echo "\ninvalidate_handle:" . $this->data['openid_invalidate_handle']; + } + } else { + echo "ns:$this->ns\nis_valid:false"; + } + die(); + break; + default: + $this->errorResponse(); + } + } else { + $this->xrds(); + } + } + + protected function checkRealm() + { + if (!isset($this->data['openid_return_to'], $this->data['openid_realm'])) { + $this->errorResponse(); + } + + $realm = str_replace('\*', '[^/]', preg_quote($this->data['openid_realm'])); + if(!preg_match("#^$realm#", $this->data['openid_return_to'])) { + $this->errorResponse(); + } + } + + protected function ax() + { + # Namespace prefix that the fields must have. + $ns = 'http://axschema.org/'; + + # First, we must find out what alias is used for AX. + # Let's check the most likely one + $alias = null; + if (isset($this->data['openid_ns_ax']) + && $this->data['openid_ns_ax'] == 'http://openid.net/srv/ax/1.0' + ) { + $alias = 'ax'; + } else { + foreach($this->data as $name => $value) { + if ($value == 'http://openid.net/srv/ax/1.0' + && preg_match('/openid_ns_(.+)/', $name, $m) + ) { + $alias = $m[1]; + break; + } + } + } + + if(!$alias) { + return null; + } + + $fields = array(); + # Now, we must search again, this time for field aliases + foreach($this->data as $name => $value) { + if (strpos($name, 'openid_' . $alias . '_type') === false + || strpos($value, $ns) === false) { + continue; + } + + $name = substr($name, strlen('openid_' . $alias . '_type_')); + $value = substr($value, strlen($ns)); + + $fields[$name] = $value; + } + + # Then, we find out what fields are required and optional + $required = array(); + $if_available = array(); + foreach(array('required','if_available') as $type) { + if(empty($this->data["openid_{$alias}_{$type}"])) { + continue; + } + $attributes = explode(',', $this->data["openid_{$alias}_{$type}"]); + foreach($attributes as $attr) { + if(empty($fields[$attr])) { + # There is an undefined field here, so we ignore it. + continue; + } + + ${$type}[] = $fields[$attr]; + } + } + + $this->data['ax'] = true; + return array('required' => $required, 'optional' => $if_available); + } + + protected function sreg() + { + $sreg_to_ax = array_flip($this->ax_to_sreg); + + $attributes = array('required' => array(), 'optional' => array()); + + if (empty($this->data['openid_sreg_required']) + && empty($this->data['openid_sreg_optional']) + ) { + return $attributes; + } + + foreach(array('required', 'optional') as $type) { + foreach(explode(',',$this->data['openid_sreg_' . $type]) as $attr) { + if(empty($sreg_to_ax[$attr])) { + # Undefined attribute in SREG request. + # Shouldn't happen, but we check anyway. + continue; + } + + $attributes[$type][] = $sreg_to_ax[$attr]; + } + } + + return $attributes; + } + + /** + * Aids an RP in assertion verification. + * @return bool Information whether the verification suceeded. + */ + protected function verify() + { + # Firstly, we need to make sure that there's an association. + # Otherwise the verification will fail, + # because we've signed assoc_handle in the assertion + if(empty($this->assoc)) { + return false; + } + + # Next, we check that it's a private association, + # i.e. one made without RP input. + # Otherwise, the RP shouldn't ask us to verify. + if(empty($this->assoc['private'])) { + return false; + } + + # Now we have to check if the nonce is correct, to prevent replay attacks. + if($this->data['openid_response_nonce'] != $this->assoc['nonce']) { + return false; + } + + # Getting the signed fields for signature. + $sig = array(); + $signed = explode(',', $this->data['openid_signed']); + foreach($signed as $field) { + $name = strtr($field, '.', '_'); + if(!isset($this->data['openid_' . $name])) { + return false; + } + + $sig[$field] = $this->data['openid_' . $name]; + } + + # Computing the signature and checking if it matches. + $sig = $this->keyValueForm($sig); + if ($this->data['openid_sig'] != + base64_encode(hash_hmac($this->assoc['hash'], $sig, $this->assoc['mac'], true)) + ) { + return false; + } + + # Clearing the nonce, so that it won't be used again. + $this->assoc['nonce'] = null; + + if(empty($this->assoc['private'])) { + # Commiting changes to the association. + $this->setAssoc($this->assoc['handle'], $this->assoc); + } else { + # Private associations shouldn't be used again, se we can as well delete them. + $this->delAssoc($this->assoc['handle']); + } + + # Nothing has failed, so the verification was a success. + return true; + } + + /** + * Performs association with an RP. + */ + protected function associate() + { + # Rejecting no-encryption without TLS. + if(empty($_SERVER['HTTPS']) && $this->data['openid_session_type'] == 'no-encryption') { + $this->directErrorResponse(); + } + + # Checking whether we support DH at all. + if (!$this->dh && substr($this->data['openid_session_type'], 0, 2) == 'DH') { + $this->redirect($this->response(array( + 'openid.error' => 'DH not supported', + 'openid.error_code' => 'unsupported-type', + 'openid.session_type' => 'no-encryption' + ))); + } + + # Creating the association + $this->assoc = array(); + $this->assoc['hash'] = $this->data['openid_assoc_type'] == 'HMAC-SHA256' ? 'sha256' : 'sha1'; + $this->assoc['handle'] = $this->assoc_handle(); + + # Getting the shared secret + if($this->data['openid_session_type'] == 'no-encryption') { + $this->assoc['mac'] = base64_encode($this->shared_secret($this->assoc['hash'])); + } else { + $this->dh(); + } + + # Preparing the direct response... + $response = array( + 'ns' => $this->ns, + 'assoc_handle' => $this->assoc['handle'], + 'assoc_type' => $this->data['openid_assoc_type'], + 'session_type' => $this->data['openid_session_type'], + 'expires_in' => $this->assoc_lifetime + ); + + if(isset($this->assoc['dh_server_public'])) { + $response['dh_server_public'] = $this->assoc['dh_server_public']; + $response['enc_mac_key'] = $this->assoc['mac']; + } else { + $response['mac_key'] = $this->assoc['mac']; + } + + # ...and sending it. + echo $this->keyValueForm($response); + die(); + } + + /** + * Creates a private association. + */ + protected function generateAssociation() + { + $this->assoc = array(); + # We use sha1 by default. + $this->assoc['hash'] = 'sha1'; + $this->assoc['mac'] = $this->shared_secret('sha1'); + $this->assoc['handle'] = $this->assoc_handle(); + } + + /** + * Encrypts the MAC key using DH key exchange. + */ + protected function dh() + { + if(empty($this->data['openid_dh_modulus'])) { + $this->data['openid_dh_modulus'] = $this->default_modulus; + } + + if(empty($this->data['openid_dh_gen'])) { + $this->data['openid_dh_gen'] = $this->default_gen; + } + + if(empty($this->data['openid_dh_consumer_public'])) { + $this->directErrorResponse(); + } + + $modulus = $this->b64dec($this->data['openid_dh_modulus']); + $gen = $this->b64dec($this->data['openid_dh_gen']); + $consumerKey = $this->b64dec($this->data['openid_dh_consumer_public']); + + $privateKey = $this->keygen(strlen($modulus)); + $publicKey = $this->powmod($gen, $privateKey, $modulus); + $ss = $this->powmod($consumerKey, $privateKey, $modulus); + + $mac = $this->x_or(hash($this->assoc['hash'], $ss, true), $this->shared_secret($this->assoc['hash'])); + $this->assoc['dh_server_public'] = $this->decb64($publicKey); + $this->assoc['mac'] = base64_encode($mac); + } + + /** + * XORs two strings. + * @param String $a + * @param String $b + * @return String $a ^ $b + */ + protected function x_or($a, $b) + { + $length = strlen($a); + for($i = 0; $i < $length; $i++) { + $a[$i] = $a[$i] ^ $b[$i]; + } + + return $a; + } + + /** + * Prepares an indirect response url. + * @param array $params Parameters to be sent. + */ + protected function response($params) + { + $params += array('openid.ns' => $this->ns); + return $this->data['openid_return_to'] + . (strpos($this->data['openid_return_to'],'?') ? '&' : '?') + . http_build_query($params, '', '&'); + } + + /** + * Outputs a direct error. + */ + protected function errorResponse() + { + if(!empty($this->data['openid_return_to'])) { + $response = array( + 'openid.mode' => 'error', + 'openid.error' => 'Invalid request' + ); + $this->redirect($this->response($response)); + } else { + header('HTTP/1.1 400 Bad Request'); + $response = array( + 'ns' => $this->ns, + 'error' => 'Invalid request' + ); + echo $this->keyValueForm($response); + } + die(); + } + + /** + * Sends an positive assertion. + * @param String $identity the OP-Local Identifier that is being authenticated. + * @param Array $attributes User attributes to be sent. + */ + protected function positiveResponse($identity, $attributes) + { + # We generate a private association if there is none established. + if(!$this->assoc) { + $this->generateAssociation(); + $this->assoc['private'] = true; + } + + # We set openid.identity (and openid.claimed_id if necessary) to our $identity + if($this->data['openid_identity'] == $this->data['openid_claimed_id']) { + $this->data['openid_claimed_id'] = $identity; + } + $this->data['openid_identity'] = $identity; + + # Preparing fields to be signed + $params = array( + 'op_endpoint' => $this->serverLocation, + 'claimed_id' => $this->data['openid_claimed_id'], + 'identity' => $this->data['openid_identity'], + 'return_to' => $this->data['openid_return_to'], + 'realm' => $this->data['openid_realm'], + 'response_nonce' => gmdate("Y-m-d\TH:i:s\Z"), + 'assoc_handle' => $this->assoc['handle'], + ); + + $params += $this->responseAttributes($attributes); + + # Has the RP used an invalid association handle? + if (isset($this->data['openid_assoc_handle']) + && $this->data['openid_assoc_handle'] != $this->assoc['handle'] + ) { + $params['invalidate_handle'] = $this->data['openid_assoc_handle']; + } + + # Signing the $params + $sig = hash_hmac($this->assoc['hash'], $this->keyValueForm($params), $this->assoc['mac'], true); + $req = array( + 'openid.mode' => 'id_res', + 'openid.signed' => implode(',', array_keys($params)), + 'openid.sig' => base64_encode($sig), + ); + + # Saving the nonce and commiting the association. + $this->assoc['nonce'] = $params['response_nonce']; + $this->setAssoc($this->assoc['handle'], $this->assoc); + + # Preparing and sending the response itself + foreach($params as $name => $value) { + $req['openid.' . $name] = $value; + } + + $this->redirect($this->response($req)); + } + + /** + * Prepares an array of attributes to send + */ + protected function responseAttributes($attributes) + { + if(!$attributes) return array(); + + $ns = 'http://axschema.org/'; + + $response = array(); + if(isset($this->data['ax'])) { + $response['ns.ax'] = 'http://openid.net/srv/ax/1.0'; + foreach($attributes as $name => $value) { + $alias = strtr($name, '/', '_'); + $response['ax.type.' . $alias] = $ns . $name; + $response['ax.value.' . $alias] = $value; + } + return $response; + } + + foreach($attributes as $name => $value) { + if(!isset($this->ax_to_sreg[$name])) { + continue; + } + + $response['sreg.' . $this->ax_to_sreg[$name]] = $value; + } + return $response; + } + + /** + * Encodes fields in key-value form. + * @param Array $params Fields to be encoded. + * @return String $params in key-value form. + */ + protected function keyValueForm($params) + { + $str = ''; + foreach($params as $name => $value) { + $str .= "$name:$value\n"; + } + + return $str; + } + + /** + * Responds with an information that the user has canceled authentication. + */ + protected function cancel() + { + $this->redirect($this->response(array('openid.mode' => 'cancel'))); + } + + /** + * Converts base64 encoded number to it's decimal representation. + * @param String $str base64 encoded number. + * @return String Decimal representation of that number. + */ + protected function b64dec($str) + { + $bytes = unpack('C*', base64_decode($str)); + $n = 0; + foreach($bytes as $byte) { + $n = $this->add($this->mul($n, 256), $byte); + } + + return $n; + } + + /** + * Complements b64dec. + */ + protected function decb64($num) + { + $bytes = array(); + while($num) { + array_unshift($bytes, $this->mod($num, 256)); + $num = $this->div($num, 256); + } + + if($bytes && $bytes[0] > 127) { + array_unshift($bytes,0); + } + + array_unshift($bytes, 'C*'); + + return base64_encode(call_user_func_array('pack', $bytes)); + } + + function __call($name, $args) + { + switch($name) { + case 'add': + case 'mul': + case 'pow': + case 'mod': + case 'div': + case 'powmod': + if(function_exists('gmp_strval')) { + return gmp_strval(call_user_func_array($this->$name, $args)); + } + return call_user_func_array($this->$name, $args); + default: + throw new BadMethodCallException(); + } + } +} diff --git a/pacotes/twitteroauth/DOCUMENTATION b/pacotes/twitteroauth/DOCUMENTATION new file mode 100644 index 0000000..4ebc207 --- /dev/null +++ b/pacotes/twitteroauth/DOCUMENTATION @@ -0,0 +1,120 @@ +TwitterOAuth documentation. + + + +GET THE CODE +==================== +You can pull the latest development version using git: +git clone git://github.com/abraham/twitteroauth.git + +Or you can download the latest release by visiting: +http://github.com/abraham/twitteroauth/downloads + + +FLOW OVERVIEW +==================== +1) Build TwitterOAuth object using client credentials. +2) Request temporary credentials from Twitter. +3) Build authorize URL for Twitter. +4) Redirect user to authorize URL. +5) User authorizes access and returns from Twitter. +6) Rebuild TwitterOAuth object with client credentials and temporary credentials. +7) Get token credentials from Twitter. +8) Rebuild TwitterOAuth object with client credentials and token credentials. +9) Query Twitter API. + + +TERMINOLOGY +==================== +The terminology has changed since 0.1.x to better match the draft-hammer-oauth IETF +RFC. You can read that at http://tools.ietf.org/html/draft-hammer-oauth. Some of the +terms will differ from those Twitter uses as well. + +client credentials - Consumer key/secret you get when registering an app with Twitter. +temporary credentials - Previously known as the request token. +token credentials - Previously known as the access token. + + +PARAMETERS +==================== +There are a number of parameters you can modify after creating a TwitterOAuth object. + +Switch to XML instead of JSON. +$connection->format = 'xml'; + +Stop auto decoding JSON. +$connection->decode_json = FALSE; + +Custom useragent. +$connection->useragent = 'Custom useragent string'; + +Verify Twitters SSL certificate. +$connection->ssl_verifypeer = TRUE; + +There are several more you can find in TwitterOAuth.php. + + + +EXTENDED FLOW USING EXAMPLE CODE +==================== +To use TwitterOAuth with the Twitter API you need TwitterOAuth.php, OAuth.php and +client credentials. You can get client credentials by registering your application at +https://twitter.com/apps. + +The example files are explained below. + +0) Users start out on connect.php which displays the "Sign in with Twitter" image hyperlinked +to redirect.php. This button should be displayed on your homepage in your login section. The +client credentials are saved in config.php as CONSUMER_KEY and CONSUMER_SECRET. You can +save a static callback URL in the app settings page, in the config file or use a dynamic +callback URL later in step 2. In example use http://example.com/callback.php. + +1) When a user lands on redirect.php we build a new TwitterOAuth object using the client +credentials. If you have your own configuration method feel free to use it instead of config.php. +$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET);// Use config.php client credentials +$connection = new TwitterOAuth('abc890', '123xyz'); + +2) Using the built $connection object you will ask Twitter for temporary credentials. If you +wish to have a dynamic callback URL for each user you can do pass a URL as a parameter. +$temporary_credentials = $connection->getRequestToken(); // Use applications registered callback. +$temporary_credentials = $connection->getRequestToken('http://example.com/callback.php?'); + +3) Now that we have temporary credentials the user has to go to Twitter and authorize the app +to access and updates their data. You can also pass a second parameter of FALSE to not use Sign +in with Twitter: http://apiwiki.twitter.com/Sign-in-with-Twitter. +$redirect_url = $connection->getAuthorizeURL($temporary_credentials); // Use Sign in with Twitter +$redirect_url = $connection->getAuthorizeURL($temporary_credentials, FALSE); + +4) You will now have a Twitter URL that you must send the user to. You can add parameters and +they will return with the user in step 5. +https://twitter.com/oauth/authenticate?oauth_token=xyz123 +https://twitter.com/oauth/authenticate?oauth_token=xyz123&info=abc // info will return with user + +5) The user is now on twitter.com and may have to login. Once authenticated with Twitter they will +will either have to click on allow/deny, or will be automatically redirected back to the callback. + +6) Now that the user has returned to callback.php and allowed access we need to build a new +TwitterOAuth object using the temporary credentials. +$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], +$_SESSION['oauth_token_secret']); + +7) Now we ask Twitter for long lasting token credentials. These are specific to the application +and user and will act like password to make future requests. If a dynamic callback URL was used +you will also have to pass the oauth_varifier parameter. Normally the token credentials would +get saved in your database but for this example we are just using sessions. +$token_credentials = $connection->getAccessToken(); // Used applications registered callback URL +$token_credentials = $connection->getAccessToken($_REQUEST['oauth_verifier']); + +7a) After getting the token credentials we redirect the user to index.php. + +8) With the token credentials we build a new TwitterOAuth object. +$connection = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, $token_credentials['oauth_token'], +$token_credentials['oauth_token_secret']); + +9) And finally we can make requests authenticated as the user. You can GET, POST, and DELETE API +methods. Directly copy the path from the API documentation and add an array of any parameter +you wish to include for the API method such as curser or in_reply_to_status_id. +$content = $connection->get('account/verify_credentials'); +$connection->post('statuses/update', array('status' => 'Text of status here', +'in_reply_to_status_id' => 123456)); +$content = $connection->delete('statuses/destroy/12345'); \ No newline at end of file diff --git a/pacotes/twitteroauth/LICENSE.txt b/pacotes/twitteroauth/LICENSE.txt new file mode 100644 index 0000000..233854f --- /dev/null +++ b/pacotes/twitteroauth/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2009 Abraham Williams - http://abrah.am - abraham@poseurte.ch + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/pacotes/twitteroauth/README.txt b/pacotes/twitteroauth/README.txt new file mode 100644 index 0000000..33cb91f --- /dev/null +++ b/pacotes/twitteroauth/README.txt @@ -0,0 +1,7 @@ +Abraham Williams | abraham@poseurte.ch | http://abrah.am | @abraham + +The first PHP library for working with Twitter's OAuth API. + +Documentation: http://wiki.github.com/abraham/twitteroauth/documentation +Source: http://github.com/abraham/twitteroauth +Twitter: http://apiwiki.twitter.com diff --git a/pacotes/twitteroauth/callback.php b/pacotes/twitteroauth/callback.php new file mode 100644 index 0000000..cc15405 --- /dev/null +++ b/pacotes/twitteroauth/callback.php @@ -0,0 +1,41 @@ +getAccessToken($_REQUEST['oauth_verifier']); + +/* Save the access tokens. Normally these would be saved in a database for future use. */ +$_SESSION['access_token'] = $access_token; + +/* Remove no longer needed request tokens */ +unset($_SESSION['oauth_token']); +unset($_SESSION['oauth_token_secret']); + +/* If HTTP response is 200 continue otherwise send to connect page to retry */ +if (200 == $connection->http_code) { + /* The user has been verified and the access tokens can be saved for future use */ + $_SESSION['status'] = 'verified'; + header('Location: ./index.php'); +} else { + /* Save HTTP status for error dialog on connnect page.*/ + header('Location: ./clearsessions.php'); +} diff --git a/pacotes/twitteroauth/clearsessions.php b/pacotes/twitteroauth/clearsessions.php new file mode 100644 index 0000000..cef4815 --- /dev/null +++ b/pacotes/twitteroauth/clearsessions.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/pacotes/twitteroauth/config.php b/pacotes/twitteroauth/config.php new file mode 100644 index 0000000..098b36c --- /dev/null +++ b/pacotes/twitteroauth/config.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/pacotes/twitteroauth/connect.php b/pacotes/twitteroauth/connect.php new file mode 100644 index 0000000..0dd01c5 --- /dev/null +++ b/pacotes/twitteroauth/connect.php @@ -0,0 +1,23 @@ +https://twitter.com/apps'; + exit; +} +*/ +// Build an image link to start the redirect process. */ +//$content = 'Sign in with Twitter'; + +/* Include HTML to display on the page. */ +//include('html.inc'); diff --git a/pacotes/twitteroauth/html.inc b/pacotes/twitteroauth/html.inc new file mode 100644 index 0000000..e093e35 --- /dev/null +++ b/pacotes/twitteroauth/html.inc @@ -0,0 +1,39 @@ + + + + Twitter OAuth in PHP + + + + +
+

Welcome to a Twitter OAuth PHP example.

+ +

This site is a basic showcase of Twitters OAuth authentication method. If you are having issues try clearing your session.

+ +

+ Links: + Source Code & + Documentation | + Contact @abraham +

+
+ + + +
+ + '.$status_text.''; ?> + +

+

+        
+      
+

+ + + diff --git a/pacotes/twitteroauth/images/darker.png b/pacotes/twitteroauth/images/darker.png new file mode 100644 index 0000000..da3081c --- /dev/null +++ b/pacotes/twitteroauth/images/darker.png @@ -0,0 +1,793 @@ + + + + + + + + + + + + images/darker.png at master from abraham's twitteroauth - GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+

Your current locale selection: English. Choose another?

+ + + + + + + + + + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + diff --git a/pacotes/twitteroauth/images/lighter.png b/pacotes/twitteroauth/images/lighter.png new file mode 100644 index 0000000..69773a2 --- /dev/null +++ b/pacotes/twitteroauth/images/lighter.png @@ -0,0 +1,793 @@ + + + + + + + + + + + + images/lighter.png at master from abraham's twitteroauth - GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+

Your current locale selection: English. Choose another?

+ + + + + + + + + + + + +
+ +
+
+
+ + + + + + + + + + + + + + + + diff --git a/pacotes/twitteroauth/index.php b/pacotes/twitteroauth/index.php new file mode 100644 index 0000000..fa3907a --- /dev/null +++ b/pacotes/twitteroauth/index.php @@ -0,0 +1,35 @@ +get('account/verify_credentials'); + +$_SESSION["openid"] = true; +$_SESSION["openid_identifier"] = "http://twitter.com/".$content->screen_name; +$_SESSION["openidusuario"] = $content->screen_name; +$_SESSION["openidservico"] = "twitter"; +$_SESSION["openidimagem"] = $content->profile_image_url; +$_SESSION["openidnome"] = $content->name; +header('Location: ../openid/login.php'); +?> diff --git a/pacotes/twitteroauth/redirect.php b/pacotes/twitteroauth/redirect.php new file mode 100644 index 0000000..dc59a17 --- /dev/null +++ b/pacotes/twitteroauth/redirect.php @@ -0,0 +1,32 @@ +getRequestToken(OAUTH_CALLBACK); + +/* Save temporary credentials to session. */ +$_SESSION['oauth_token'] = $token = $request_token['oauth_token']; +$_SESSION['oauth_token_secret'] = $request_token['oauth_token_secret']; +$_SESSION['servico'] = "twitter"; + +/* If last connection failed don't display authorization link. */ +switch ($connection->http_code) { + case 200: + /* Build authorize URL and redirect user to Twitter. */ + $url = $connection->getAuthorizeURL($token); + header('Location: '.$url ); + break; + default: + /* Show notification if something went wrong. */ + echo 'Could not connect to Twitter. Refresh the page or try again later.'; +} diff --git a/pacotes/twitteroauth/test.php b/pacotes/twitteroauth/test.php new file mode 100644 index 0000000..12b6e88 --- /dev/null +++ b/pacotes/twitteroauth/test.php @@ -0,0 +1,374 @@ +get('account/rate_limit_status'); +echo "Current API hits remaining: {$content->remaining_hits}."; + +/* Get logged in user to help with tests. */ +$user = $connection->get('account/verify_credentials'); + +$active = FALSE; +if (empty($active) || empty($_GET['confirmed']) || $_GET['confirmed'] !== 'TRUE') { + echo '

Warning! This page will make many requests to Twitter.

'; + echo '

Performing these test might max out your rate limit.

'; + echo '

Statuses/DMs will be created and deleted. Accounts will be un/followed.

'; + echo '

Profile information/design will be changed.

'; + echo '

USE A DEV ACCOUNT!

'; + echo '

Before use you must set $active = TRUE in test.php

'; + echo 'Continue or go back.'; + exit; +} + +function twitteroauth_row($method, $response, $http_code, $parameters = '') { + echo ''; + echo "{$method}"; + switch ($http_code) { + case '200': + case '304': + $color = 'green'; + break; + case '400': + case '401': + case '403': + case '404': + case '406': + $color = 'red'; + break; + case '500': + case '502': + case '503': + $color = 'orange'; + break; + default: + $color = 'grey'; + } + echo "{$http_code}"; + if (!is_string($response)) { + $response = print_r($response, TRUE); + } + if (!is_string($parameters)) { + $parameters = print_r($parameters, TRUE); + } + echo '', strlen($response), ''; + echo '', $parameters, ''; + echo ''; + echo '', substr($response, 0, 400), '...'; + echo ''; + +} + +function twitteroauth_header($header) { + echo '', $header, ''; +} + +/* Start table. */ +echo '

'; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; +echo ''; + +/** + * Help Methods. + */ +twitteroauth_header('Help Methods'); + +/* help/test */ +twitteroauth_row('help/test', $connection->get('help/test'), $connection->http_code); + + +/** + * Timeline Methods. + */ +twitteroauth_header('Timeline Methods'); + +/* statuses/public_timeline */ +twitteroauth_row('statuses/public_timeline', $connection->get('statuses/public_timeline'), $connection->http_code); + +/* statuses/public_timeline */ +twitteroauth_row('statuses/home_timeline', $connection->get('statuses/home_timeline'), $connection->http_code); + +/* statuses/friends_timeline */ +twitteroauth_row('statuses/friends_timeline', $connection->get('statuses/friends_timeline'), $connection->http_code); + +/* statuses/user_timeline */ +twitteroauth_row('statuses/user_timeline', $connection->get('statuses/user_timeline'), $connection->http_code); + +/* statuses/mentions */ +twitteroauth_row('statuses/mentions', $connection->get('statuses/mentions'), $connection->http_code); + +/* statuses/retweeted_by_me */ +twitteroauth_row('statuses/retweeted_by_me', $connection->get('statuses/retweeted_by_me'), $connection->http_code); + +/* statuses/retweeted_to_me */ +twitteroauth_row('statuses/retweeted_to_me', $connection->get('statuses/retweeted_to_me'), $connection->http_code); + +/* statuses/retweets_of_me */ +twitteroauth_row('statuses/retweets_of_me', $connection->get('statuses/retweets_of_me'), $connection->http_code); + + +/** + * Status Methods. + */ +twitteroauth_header('Status Methods'); + +/* statuses/update */ +date_default_timezone_set('GMT'); +$parameters = array('status' => date(DATE_RFC822)); +$status = $connection->post('statuses/update', $parameters); +twitteroauth_row('statuses/update', $status, $connection->http_code, $parameters); + +/* statuses/show */ +$method = "statuses/show/{$status->id}"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* statuses/destroy */ +$method = "statuses/destroy/{$status->id}"; +twitteroauth_row($method, $connection->delete($method), $connection->http_code); + +/* statuses/retweet */ +$method = 'statuses/retweet/6242973112'; +twitteroauth_row($method, $connection->post($method), $connection->http_code); + +/* statuses/retweets */ +$method = 'statuses/retweets/6242973112'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + + +/** + * User Methods. + */ +twitteroauth_header('User Methods'); + +/* users/show */ +$method = 'users/show/27831060'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* users/search */ +$parameters = array('q' => 'oauth'); +twitteroauth_row('users/search', $connection->get('users/search', $parameters), $connection->http_code, $parameters); + +/* statuses/friends */ +$method = 'statuses/friends/27831060'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* statuses/followers */ +$method = 'statuses/followers/27831060'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + + +/** + * List Methods. + */ +twitteroauth_header('List Methods'); + +/* POST lists */ +$method = "{$user->screen_name}/lists"; +$parameters = array('name' => 'Twitter OAuth'); +$list = $connection->post($method, $parameters); +twitteroauth_row($method, $list, $connection->http_code, $parameters); + +/* POST lists id */ +$method = "{$user->screen_name}/lists/{$list->id}"; +$parameters = array('name' => 'Twitter OAuth List 2'); +$list = $connection->post($method, $parameters); +twitteroauth_row($method, $list, $connection->http_code, $parameters); + +/* GET lists */ +$method = "{$user->screen_name}/lists"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* GET lists id */ +$method = "{$user->screen_name}/lists/{$list->id}"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* DELETE list */ +$method = "{$user->screen_name}/lists/{$list->id}"; +twitteroauth_row($method, $connection->delete($method), $connection->http_code); + +/* GET list statuses */ +$method = "oauthlib/lists/4097351/statuses"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* GET list members */ +$method = "{$user->screen_name}/lists/memberships"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + + +/* GET list subscriptions */ +$method = "{$user->screen_name}/lists/subscriptions"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + + +/** + * List Members Methods. + */ +twitteroauth_header('List Members Methods'); + +/* Create temp list for list member methods. */ +$method = "{$user->screen_name}/lists"; +$parameters = array('name' => 'Twitter OAuth Temp'); +$list = $connection->post($method, $parameters); + + +/* POST list members */ +$parameters = array('id' => 27831060); +$method = "{$user->screen_name}/{$list->id}/members"; +twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters); + +/* GET list members */ +$method = "{$user->screen_name}/{$list->id}/members"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* GET list members id */ +$method = "{$user->screen_name}/{$list->id}/members/27831060"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* DELETE list members */ +$parameters = array('id' => 27831060); +$method = "{$user->screen_name}/{$list->id}/members"; +twitteroauth_row($method, $connection->delete($method, $parameters), $connection->http_code, $parameters); + +/* Delete the temp list */ +$method = "{$user->screen_name}/lists/{$list->id}"; +$connection->delete($method); + + +/** + * List Subscribers Methods. + */ +twitteroauth_header('List Subscribers Methods'); + + +/* POST list subscribers */ +$method = 'oauthlib/test-list/subscribers'; +twitteroauth_row($method, $connection->post($method), $connection->http_code); + +/* GET list subscribers */ +$method = 'oauthlib/test-list/subscribers'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* GET list subscribers id */ +$method = "oauthlib/test-list/subscribers/{$user->id}"; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* DELETE list subscribers */ +$method = 'oauthlib/test-list/subscribers'; +twitteroauth_row($method, $connection->delete($method), $connection->http_code); + + +/** + * Direct Message Methdos. + */ +twitteroauth_header('Direct Message Methods'); + +/* direct_messages/new */ +$parameters = array('user_id' => $user->id, 'text' => 'Testing out @oauthlib code'); +$method = 'direct_messages/new'; +$dm = $connection->post($method, $parameters); +twitteroauth_row($method, $dm, $connection->http_code, $parameters); + +/* direct_messages */ +$method = 'direct_messages'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* direct_messages/sent */ +$method = 'direct_messages/sent'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* direct_messages/sent */ +$method = "direct_messages/destroy/{$dm->id}"; +twitteroauth_row($method, $connection->delete($method), $connection->http_code); + + +/** + * Friendships Methods. + */ +twitteroauth_header('Friendships Methods'); + +/* friendships/create */ +$method = 'friendships/create/93915746'; +twitteroauth_row($method, $connection->post($method), $connection->http_code); + +/* friendships/show */ +$parameters = array('target_id' => 27831060); +$method = 'friendships/show'; +twitteroauth_row($method, $connection->get($method, $parameters), $connection->http_code, $parameters); + +/* friendships/destroy */ +$method = 'friendships/destroy/93915746'; +twitteroauth_row($method, $connection->post($method), $connection->http_code); + + +/** + * Social Graph Methods. + */ +twitteroauth_header('Social Graph Methods'); + +/* friends/ids */ +$method = 'friends/ids'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* friends/ids */ +$method = 'friends/ids'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + + +/** + * Account Methods. + */ +twitteroauth_header('Account Methods'); + +/* account/verify_credentials */ +$method = 'account/verify_credentials'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* account/rate_limit_status */ +$method = 'account/rate_limit_status'; +twitteroauth_row($method, $connection->get($method), $connection->http_code); + +/* account/update_profile_colors */ +$parameters = array('profile_background_color' => 'fff'); +$method = 'account/update_profile_colors'; +twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters); + +/* account/update_profile */ +$parameters = array('location' => 'Teh internets'); +$method = 'account/update_profile'; +twitteroauth_row($method, $connection->post($method, $parameters), $connection->http_code, $parameters); + + + + +/** + * OAuth Methods. + */ +twitteroauth_header('OAuth Methods'); + +/* oauth/request_token */ +$oauth = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET); +twitteroauth_row('oauth/reqeust_token', $oauth->getRequestToken(), $oauth->http_code); diff --git a/pacotes/twitteroauth/twitteroauth/OAuth.php b/pacotes/twitteroauth/twitteroauth/OAuth.php new file mode 100644 index 0000000..67a94c4 --- /dev/null +++ b/pacotes/twitteroauth/twitteroauth/OAuth.php @@ -0,0 +1,874 @@ +key = $key; + $this->secret = $secret; + $this->callback_url = $callback_url; + } + + function __toString() { + return "OAuthConsumer[key=$this->key,secret=$this->secret]"; + } +} + +class OAuthToken { + // access tokens and request tokens + public $key; + public $secret; + + /** + * key = the token + * secret = the token secret + */ + function __construct($key, $secret) { + $this->key = $key; + $this->secret = $secret; + } + + /** + * generates the basic string serialization of a token that a server + * would respond to request_token and access_token calls with + */ + function to_string() { + return "oauth_token=" . + OAuthUtil::urlencode_rfc3986($this->key) . + "&oauth_token_secret=" . + OAuthUtil::urlencode_rfc3986($this->secret); + } + + function __toString() { + return $this->to_string(); + } +} + +/** + * A class for implementing a Signature Method + * See section 9 ("Signing Requests") in the spec + */ +abstract class OAuthSignatureMethod { + /** + * Needs to return the name of the Signature Method (ie HMAC-SHA1) + * @return string + */ + abstract public function get_name(); + + /** + * Build up the signature + * NOTE: The output of this function MUST NOT be urlencoded. + * the encoding is handled in OAuthRequest when the final + * request is serialized + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @return string + */ + abstract public function build_signature($request, $consumer, $token); + + /** + * Verifies that a given signature is correct + * @param OAuthRequest $request + * @param OAuthConsumer $consumer + * @param OAuthToken $token + * @param string $signature + * @return bool + */ + public function check_signature($request, $consumer, $token, $signature) { + $built = $this->build_signature($request, $consumer, $token); + return $built == $signature; + } +} + +/** + * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] + * where the Signature Base String is the text and the key is the concatenated values (each first + * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' + * character (ASCII code 38) even if empty. + * - Chapter 9.2 ("HMAC-SHA1") + */ +class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { + function get_name() { + return "HMAC-SHA1"; + } + + public function build_signature($request, $consumer, $token) { + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + + return base64_encode(hash_hmac('sha1', $base_string, $key, true)); + } +} + +/** + * The PLAINTEXT method does not provide any security protection and SHOULD only be used + * over a secure channel such as HTTPS. It does not use the Signature Base String. + * - Chapter 9.4 ("PLAINTEXT") + */ +class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { + public function get_name() { + return "PLAINTEXT"; + } + + /** + * oauth_signature is set to the concatenated encoded values of the Consumer Secret and + * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is + * empty. The result MUST be encoded again. + * - Chapter 9.4.1 ("Generating Signatures") + * + * Please note that the second encoding MUST NOT happen in the SignatureMethod, as + * OAuthRequest handles this! + */ + public function build_signature($request, $consumer, $token) { + $key_parts = array( + $consumer->secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + $request->base_string = $key; + + return $key; + } +} + +/** + * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in + * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for + * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a + * verified way to the Service Provider, in a manner which is beyond the scope of this + * specification. + * - Chapter 9.3 ("RSA-SHA1") + */ +abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { + public function get_name() { + return "RSA-SHA1"; + } + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // (2) fetch via http using a url provided by the requester + // (3) some sort of specific discovery code based on request + // + // Either way should return a string representation of the certificate + protected abstract function fetch_public_cert(&$request); + + // Up to the SP to implement this lookup of keys. Possible ideas are: + // (1) do a lookup in a table of trusted certs keyed off of consumer + // + // Either way should return a string representation of the certificate + protected abstract function fetch_private_cert(&$request); + + public function build_signature($request, $consumer, $token) { + $base_string = $request->get_signature_base_string(); + $request->base_string = $base_string; + + // Fetch the private key cert based on the request + $cert = $this->fetch_private_cert($request); + + // Pull the private key ID from the certificate + $privatekeyid = openssl_get_privatekey($cert); + + // Sign using the key + $ok = openssl_sign($base_string, $signature, $privatekeyid); + + // Release the key resource + openssl_free_key($privatekeyid); + + return base64_encode($signature); + } + + public function check_signature($request, $consumer, $token, $signature) { + $decoded_sig = base64_decode($signature); + + $base_string = $request->get_signature_base_string(); + + // Fetch the public key cert based on the request + $cert = $this->fetch_public_cert($request); + + // Pull the public key ID from the certificate + $publickeyid = openssl_get_publickey($cert); + + // Check the computed signature against the one passed in the query + $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); + + // Release the key resource + openssl_free_key($publickeyid); + + return $ok == 1; + } +} + +class OAuthRequest { + private $parameters; + private $http_method; + private $http_url; + // for debug purposes + public $base_string; + public static $version = '1.0'; + public static $POST_INPUT = 'php://input'; + + function __construct($http_method, $http_url, $parameters=NULL) { + @$parameters or $parameters = array(); + $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); + $this->parameters = $parameters; + $this->http_method = $http_method; + $this->http_url = $http_url; + } + + + /** + * attempt to build up a request from what was passed to the server + */ + public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { + $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") + ? 'http' + : 'https'; + @$http_url or $http_url = $scheme . + '://' . $_SERVER['HTTP_HOST'] . + ':' . + $_SERVER['SERVER_PORT'] . + $_SERVER['REQUEST_URI']; + @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; + + // We weren't handed any parameters, so let's find the ones relevant to + // this request. + // If you run XML-RPC or similar you should use this to provide your own + // parsed parameter-list + if (!$parameters) { + // Find request headers + $request_headers = OAuthUtil::get_headers(); + + // Parse the query-string to find GET parameters + $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); + + // It's a POST request of the proper content-type, so parse POST + // parameters and add those overriding any duplicates from GET + if ($http_method == "POST" + && @strstr($request_headers["Content-Type"], + "application/x-www-form-urlencoded") + ) { + $post_data = OAuthUtil::parse_parameters( + file_get_contents(self::$POST_INPUT) + ); + $parameters = array_merge($parameters, $post_data); + } + + // We have a Authorization-header with OAuth data. Parse the header + // and add those overriding any duplicates from GET or POST + if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { + $header_parameters = OAuthUtil::split_header( + $request_headers['Authorization'] + ); + $parameters = array_merge($parameters, $header_parameters); + } + + } + + return new OAuthRequest($http_method, $http_url, $parameters); + } + + /** + * pretty much a helper function to set up the request + */ + public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { + @$parameters or $parameters = array(); + $defaults = array("oauth_version" => OAuthRequest::$version, + "oauth_nonce" => OAuthRequest::generate_nonce(), + "oauth_timestamp" => OAuthRequest::generate_timestamp(), + "oauth_consumer_key" => $consumer->key); + if ($token) + $defaults['oauth_token'] = $token->key; + + $parameters = array_merge($defaults, $parameters); + + return new OAuthRequest($http_method, $http_url, $parameters); + } + + public function set_parameter($name, $value, $allow_duplicates = true) { + if ($allow_duplicates && isset($this->parameters[$name])) { + // We have already added parameter(s) with this name, so add to the list + if (is_scalar($this->parameters[$name])) { + // This is the first duplicate, so transform scalar (string) + // into an array so we can add the duplicates + $this->parameters[$name] = array($this->parameters[$name]); + } + + $this->parameters[$name][] = $value; + } else { + $this->parameters[$name] = $value; + } + } + + public function get_parameter($name) { + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + } + + public function get_parameters() { + return $this->parameters; + } + + public function unset_parameter($name) { + unset($this->parameters[$name]); + } + + /** + * The request parameters, sorted and concatenated into a normalized string. + * @return string + */ + public function get_signable_parameters() { + // Grab all parameters + $params = $this->parameters; + + // Remove oauth_signature if present + // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") + if (isset($params['oauth_signature'])) { + unset($params['oauth_signature']); + } + + return OAuthUtil::build_http_query($params); + } + + /** + * Returns the base string of this request + * + * The base string defined as the method, the url + * and the parameters (normalized), each urlencoded + * and the concated with &. + */ + public function get_signature_base_string() { + $parts = array( + $this->get_normalized_http_method(), + $this->get_normalized_http_url(), + $this->get_signable_parameters() + ); + + $parts = OAuthUtil::urlencode_rfc3986($parts); + + return implode('&', $parts); + } + + /** + * just uppercases the http method + */ + public function get_normalized_http_method() { + return strtoupper($this->http_method); + } + + /** + * parses the url and rebuilds it to be + * scheme://host/path + */ + public function get_normalized_http_url() { + $parts = parse_url($this->http_url); + + $port = @$parts['port']; + $scheme = $parts['scheme']; + $host = $parts['host']; + $path = @$parts['path']; + + $port or $port = ($scheme == 'https') ? '443' : '80'; + + if (($scheme == 'https' && $port != '443') + || ($scheme == 'http' && $port != '80')) { + $host = "$host:$port"; + } + return "$scheme://$host$path"; + } + + /** + * builds a url usable for a GET request + */ + public function to_url() { + $post_data = $this->to_postdata(); + $out = $this->get_normalized_http_url(); + if ($post_data) { + $out .= '?'.$post_data; + } + return $out; + } + + /** + * builds the data one would send in a POST request + */ + public function to_postdata() { + return OAuthUtil::build_http_query($this->parameters); + } + + /** + * builds the Authorization: header + */ + public function to_header($realm=null) { + $first = true; + if($realm) { + $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"'; + $first = false; + } else + $out = 'Authorization: OAuth'; + + $total = array(); + foreach ($this->parameters as $k => $v) { + if (substr($k, 0, 5) != "oauth") continue; + if (is_array($v)) { + throw new OAuthException('Arrays not supported in headers'); + } + $out .= ($first) ? ' ' : ','; + $out .= OAuthUtil::urlencode_rfc3986($k) . + '="' . + OAuthUtil::urlencode_rfc3986($v) . + '"'; + $first = false; + } + return $out; + } + + public function __toString() { + return $this->to_url(); + } + + + public function sign_request($signature_method, $consumer, $token) { + $this->set_parameter( + "oauth_signature_method", + $signature_method->get_name(), + false + ); + $signature = $this->build_signature($signature_method, $consumer, $token); + $this->set_parameter("oauth_signature", $signature, false); + } + + public function build_signature($signature_method, $consumer, $token) { + $signature = $signature_method->build_signature($this, $consumer, $token); + return $signature; + } + + /** + * util function: current timestamp + */ + private static function generate_timestamp() { + return time(); + } + + /** + * util function: current nonce + */ + private static function generate_nonce() { + $mt = microtime(); + $rand = mt_rand(); + + return md5($mt . $rand); // md5s look nicer than numbers + } +} + +class OAuthServer { + protected $timestamp_threshold = 300; // in seconds, five minutes + protected $version = '1.0'; // hi blaine + protected $signature_methods = array(); + + protected $data_store; + + function __construct($data_store) { + $this->data_store = $data_store; + } + + public function add_signature_method($signature_method) { + $this->signature_methods[$signature_method->get_name()] = + $signature_method; + } + + // high level functions + + /** + * process a request_token request + * returns the request token on success + */ + public function fetch_request_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // no token required for the initial token request + $token = NULL; + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $callback = $request->get_parameter('oauth_callback'); + $new_token = $this->data_store->new_request_token($consumer, $callback); + + return $new_token; + } + + /** + * process an access_token request + * returns the access token on success + */ + public function fetch_access_token(&$request) { + $this->get_version($request); + + $consumer = $this->get_consumer($request); + + // requires authorized request token + $token = $this->get_token($request, $consumer, "request"); + + $this->check_signature($request, $consumer, $token); + + // Rev A change + $verifier = $request->get_parameter('oauth_verifier'); + $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); + + return $new_token; + } + + /** + * verify an api call, checks all the parameters + */ + public function verify_request(&$request) { + $this->get_version($request); + $consumer = $this->get_consumer($request); + $token = $this->get_token($request, $consumer, "access"); + $this->check_signature($request, $consumer, $token); + return array($consumer, $token); + } + + // Internals from here + /** + * version 1 + */ + private function get_version(&$request) { + $version = $request->get_parameter("oauth_version"); + if (!$version) { + // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. + // Chapter 7.0 ("Accessing Protected Ressources") + $version = '1.0'; + } + if ($version !== $this->version) { + throw new OAuthException("OAuth version '$version' not supported"); + } + return $version; + } + + /** + * figure out the signature with some defaults + */ + private function get_signature_method(&$request) { + $signature_method = + @$request->get_parameter("oauth_signature_method"); + + if (!$signature_method) { + // According to chapter 7 ("Accessing Protected Ressources") the signature-method + // parameter is required, and we can't just fallback to PLAINTEXT + throw new OAuthException('No signature method parameter. This parameter is required'); + } + + if (!in_array($signature_method, + array_keys($this->signature_methods))) { + throw new OAuthException( + "Signature method '$signature_method' not supported " . + "try one of the following: " . + implode(", ", array_keys($this->signature_methods)) + ); + } + return $this->signature_methods[$signature_method]; + } + + /** + * try to find the consumer for the provided request's consumer key + */ + private function get_consumer(&$request) { + $consumer_key = @$request->get_parameter("oauth_consumer_key"); + if (!$consumer_key) { + throw new OAuthException("Invalid consumer key"); + } + + $consumer = $this->data_store->lookup_consumer($consumer_key); + if (!$consumer) { + throw new OAuthException("Invalid consumer"); + } + + return $consumer; + } + + /** + * try to find the token for the provided request's token key + */ + private function get_token(&$request, $consumer, $token_type="access") { + $token_field = @$request->get_parameter('oauth_token'); + $token = $this->data_store->lookup_token( + $consumer, $token_type, $token_field + ); + if (!$token) { + throw new OAuthException("Invalid $token_type token: $token_field"); + } + return $token; + } + + /** + * all-in-one function to check the signature on a request + * should guess the signature method appropriately + */ + private function check_signature(&$request, $consumer, $token) { + // this should probably be in a different method + $timestamp = @$request->get_parameter('oauth_timestamp'); + $nonce = @$request->get_parameter('oauth_nonce'); + + $this->check_timestamp($timestamp); + $this->check_nonce($consumer, $token, $nonce, $timestamp); + + $signature_method = $this->get_signature_method($request); + + $signature = $request->get_parameter('oauth_signature'); + $valid_sig = $signature_method->check_signature( + $request, + $consumer, + $token, + $signature + ); + + if (!$valid_sig) { + throw new OAuthException("Invalid signature"); + } + } + + /** + * check that the timestamp is new enough + */ + private function check_timestamp($timestamp) { + if( ! $timestamp ) + throw new OAuthException( + 'Missing timestamp parameter. The parameter is required' + ); + + // verify that timestamp is recentish + $now = time(); + if (abs($now - $timestamp) > $this->timestamp_threshold) { + throw new OAuthException( + "Expired timestamp, yours $timestamp, ours $now" + ); + } + } + + /** + * check that the nonce is not repeated + */ + private function check_nonce($consumer, $token, $nonce, $timestamp) { + if( ! $nonce ) + throw new OAuthException( + 'Missing nonce parameter. The parameter is required' + ); + + // verify that the nonce is uniqueish + $found = $this->data_store->lookup_nonce( + $consumer, + $token, + $nonce, + $timestamp + ); + if ($found) { + throw new OAuthException("Nonce already used: $nonce"); + } + } + +} + +class OAuthDataStore { + function lookup_consumer($consumer_key) { + // implement me + } + + function lookup_token($consumer, $token_type, $token) { + // implement me + } + + function lookup_nonce($consumer, $token, $nonce, $timestamp) { + // implement me + } + + function new_request_token($consumer, $callback = null) { + // return a new token attached to this consumer + } + + function new_access_token($token, $consumer, $verifier = null) { + // return a new access token attached to this consumer + // for the user associated with this token if the request token + // is authorized + // should also invalidate the request token + } + +} + +class OAuthUtil { + public static function urlencode_rfc3986($input) { + if (is_array($input)) { + return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); + } else if (is_scalar($input)) { + return str_replace( + '+', + ' ', + str_replace('%7E', '~', rawurlencode($input)) + ); + } else { + return ''; + } +} + + + // This decode function isn't taking into consideration the above + // modifications to the encoding process. However, this method doesn't + // seem to be used anywhere so leaving it as is. + public static function urldecode_rfc3986($string) { + return urldecode($string); + } + + // Utility function for turning the Authorization: header into + // parameters, has to do some unescaping + // Can filter out any non-oauth parameters if needed (default behaviour) + public static function split_header($header, $only_allow_oauth_parameters = true) { + $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/'; + $offset = 0; + $params = array(); + while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { + $match = $matches[0]; + $header_name = $matches[2][0]; + $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0]; + if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) { + $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content); + } + $offset = $match[1] + strlen($match[0]); + } + + if (isset($params['realm'])) { + unset($params['realm']); + } + + return $params; + } + + // helper to try to sort out headers for people who aren't running apache + public static function get_headers() { + if (function_exists('apache_request_headers')) { + // we need this to get the actual Authorization: header + // because apache tends to tell us it doesn't exist + $headers = apache_request_headers(); + + // sanitize the output of apache_request_headers because + // we always want the keys to be Cased-Like-This and arh() + // returns the headers in the same case as they are in the + // request + $out = array(); + foreach( $headers AS $key => $value ) { + $key = str_replace( + " ", + "-", + ucwords(strtolower(str_replace("-", " ", $key))) + ); + $out[$key] = $value; + } + } else { + // otherwise we don't have apache and are just going to have to hope + // that $_SERVER actually contains what we need + $out = array(); + if( isset($_SERVER['CONTENT_TYPE']) ) + $out['Content-Type'] = $_SERVER['CONTENT_TYPE']; + if( isset($_ENV['CONTENT_TYPE']) ) + $out['Content-Type'] = $_ENV['CONTENT_TYPE']; + + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) == "HTTP_") { + // this is chaos, basically it is just there to capitalize the first + // letter of every word that is not an initial HTTP and strip HTTP + // code from przemek + $key = str_replace( + " ", + "-", + ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) + ); + $out[$key] = $value; + } + } + } + return $out; + } + + // This function takes a input like a=b&a=c&d=e and returns the parsed + // parameters like this + // array('a' => array('b','c'), 'd' => 'e') + public static function parse_parameters( $input ) { + if (!isset($input) || !$input) return array(); + + $pairs = explode('&', $input); + + $parsed_parameters = array(); + foreach ($pairs as $pair) { + $split = explode('=', $pair, 2); + $parameter = OAuthUtil::urldecode_rfc3986($split[0]); + $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; + + if (isset($parsed_parameters[$parameter])) { + // We have already recieved parameter(s) with this name, so add to the list + // of parameters with this name + + if (is_scalar($parsed_parameters[$parameter])) { + // This is the first duplicate, so transform scalar (string) into an array + // so we can add the duplicates + $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]); + } + + $parsed_parameters[$parameter][] = $value; + } else { + $parsed_parameters[$parameter] = $value; + } + } + return $parsed_parameters; + } + + public static function build_http_query($params) { + if (!$params) return ''; + + // Urlencode both keys and values + $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); + $values = OAuthUtil::urlencode_rfc3986(array_values($params)); + $params = array_combine($keys, $values); + + // Parameters are sorted by name, using lexicographical byte value ordering. + // Ref: Spec: 9.1.1 (1) + uksort($params, 'strcmp'); + + $pairs = array(); + foreach ($params as $parameter => $value) { + if (is_array($value)) { + // If two or more parameters share the same name, they are sorted by their value + // Ref: Spec: 9.1.1 (1) + natsort($value); + foreach ($value as $duplicate_value) { + $pairs[] = $parameter . '=' . $duplicate_value; + } + } else { + $pairs[] = $parameter . '=' . $value; + } + } + // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) + // Each name-value pair is separated by an '&' character (ASCII code 38) + return implode('&', $pairs); + } +} + +?> diff --git a/pacotes/twitteroauth/twitteroauth/twitteroauth.php b/pacotes/twitteroauth/twitteroauth/twitteroauth.php new file mode 100644 index 0000000..674308a --- /dev/null +++ b/pacotes/twitteroauth/twitteroauth/twitteroauth.php @@ -0,0 +1,245 @@ +http_status; } + function lastAPICall() { return $this->last_api_call; } + + /** + * construct TwitterOAuth object + */ + function __construct($consumer_key, $consumer_secret, $oauth_token = NULL, $oauth_token_secret = NULL) { + $this->sha1_method = new OAuthSignatureMethod_HMAC_SHA1(); + $this->consumer = new OAuthConsumer($consumer_key, $consumer_secret); + if (!empty($oauth_token) && !empty($oauth_token_secret)) { + $this->token = new OAuthConsumer($oauth_token, $oauth_token_secret); + } else { + $this->token = NULL; + } + } + + + /** + * Get a request_token from Twitter + * + * @returns a key/value array containing oauth_token and oauth_token_secret + */ + function getRequestToken($oauth_callback = NULL) { + $parameters = array(); + if (!empty($oauth_callback)) { + $parameters['oauth_callback'] = $oauth_callback; + } + $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); + return $token; + } + + /** + * Get the authorize URL + * + * @returns a string + */ + function getAuthorizeURL($token, $sign_in_with_twitter = TRUE) { + if (is_array($token)) { + $token = $token['oauth_token']; + } + if (empty($sign_in_with_twitter)) { + return $this->authorizeURL() . "?oauth_token={$token}"; + } else { + return $this->authenticateURL() . "?oauth_token={$token}"; + } + } + + /** + * Exchange request token and secret for an access token and + * secret, to sign API calls. + * + * @returns array("oauth_token" => "the-access-token", + * "oauth_token_secret" => "the-access-secret", + * "user_id" => "9436992", + * "screen_name" => "abraham") + */ + function getAccessToken($oauth_verifier = FALSE) { + $parameters = array(); + if (!empty($oauth_verifier)) { + $parameters['oauth_verifier'] = $oauth_verifier; + } + $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); + return $token; + } + + /** + * One time exchange of username and password for access token and secret. + * + * @returns array("oauth_token" => "the-access-token", + * "oauth_token_secret" => "the-access-secret", + * "user_id" => "9436992", + * "screen_name" => "abraham", + * "x_auth_expires" => "0") + */ + function getXAuthToken($username, $password) { + $parameters = array(); + $parameters['x_auth_username'] = $username; + $parameters['x_auth_password'] = $password; + $parameters['x_auth_mode'] = 'client_auth'; + $request = $this->oAuthRequest($this->accessTokenURL(), 'POST', $parameters); + $token = OAuthUtil::parse_parameters($request); + $this->token = new OAuthConsumer($token['oauth_token'], $token['oauth_token_secret']); + return $token; + } + + /** + * GET wrapper for oAuthRequest. + */ + function get($url, $parameters = array()) { + $response = $this->oAuthRequest($url, 'GET', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + return $response; + } + + /** + * POST wrapper for oAuthRequest. + */ + function post($url, $parameters = array()) { + $response = $this->oAuthRequest($url, 'POST', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + return $response; + } + + /** + * DELETE wrapper for oAuthReqeust. + */ + function delete($url, $parameters = array()) { + $response = $this->oAuthRequest($url, 'DELETE', $parameters); + if ($this->format === 'json' && $this->decode_json) { + return json_decode($response); + } + return $response; + } + + /** + * Format and sign an OAuth / API request + */ + function oAuthRequest($url, $method, $parameters) { + if (strrpos($url, 'https://') !== 0 && strrpos($url, 'http://') !== 0) { + $url = "{$this->host}{$url}.{$this->format}"; + } + $request = OAuthRequest::from_consumer_and_token($this->consumer, $this->token, $method, $url, $parameters); + $request->sign_request($this->sha1_method, $this->consumer, $this->token); + switch ($method) { + case 'GET': + return $this->http($request->to_url(), 'GET'); + default: + return $this->http($request->get_normalized_http_url(), $method, $request->to_postdata()); + } + } + + /** + * Make an HTTP request + * + * @return API results + */ + function http($url, $method, $postfields = NULL) { + $this->http_info = array(); + $ci = curl_init(); + /* Curl settings */ + curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent); + curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->connecttimeout); + curl_setopt($ci, CURLOPT_TIMEOUT, $this->timeout); + curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ci, CURLOPT_HTTPHEADER, array('Expect:')); + curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer); + curl_setopt($ci, CURLOPT_HEADERFUNCTION, array($this, 'getHeader')); + curl_setopt($ci, CURLOPT_HEADER, FALSE); + + switch ($method) { + case 'POST': + curl_setopt($ci, CURLOPT_POST, TRUE); + if (!empty($postfields)) { + curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields); + } + break; + case 'DELETE': + curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE'); + if (!empty($postfields)) { + $url = "{$url}?{$postfields}"; + } + } + + curl_setopt($ci, CURLOPT_URL, $url); + $response = curl_exec($ci); + $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE); + $this->http_info = array_merge($this->http_info, curl_getinfo($ci)); + $this->url = $url; + curl_close ($ci); + return $response; + } + + /** + * Get the header info to store. + */ + function getHeader($ch, $header) { + $i = strpos($header, ':'); + if (!empty($i)) { + $key = str_replace('-', '_', strtolower(substr($header, 0, $i))); + $value = trim(substr($header, $i + 2)); + $this->http_header[$key] = $value; + } + return strlen($header); + } +} diff --git a/testainstal.php b/testainstal.php index 0c9aef3..4ad56ac 100644 --- a/testainstal.php +++ b/testainstal.php @@ -115,7 +115,8 @@ $tabelas = array( "i3geoadmin_grupos"=>"it,es,en,desc_grupo,id_grupo,nome_grupo", "i3geoadmin_subgrupos"=>"it,es,en,desc_subgrupo,id_subgrupo,nome_subgrupo", "i3geoadmin_temas"=>"it,es,en,kmz_tema,nacessos,id_tema,kml_tema,ogc_tema,download_tema,tags_tema,tipoa_tema,link_tema,desc_tema,nome_tema,codigo_tema", - "i3geoadmin_menus"=>"it,es,en,publicado_menu,perfil_menu,aberto,desc_menu,id_menu,nome_menu" + "i3geoadmin_menus"=>"it,es,en,publicado_menu,perfil_menu,aberto,desc_menu,id_menu,nome_menu", + "i3geoadmin_comentarios"=>"comentario,data,openidnome,openidimagem,openidservico,openidusuario,openidurl,id_tema" ); include_once("admin/php/conexao.php"); foreach(array_keys($tabelas) as $tabela) -- libgit2 0.21.2
API MethodHTTP CodeResponse LengthParameters
Response Snippet