diff --git a/main/attendance/attendance_controller.php b/main/attendance/attendance_controller.php index 6d4d026fb3..f256ab7f4f 100755 --- a/main/attendance/attendance_controller.php +++ b/main/attendance/attendance_controller.php @@ -303,7 +303,7 @@ class AttendanceController $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh( api_get_user_id(), api_get_course_info() - ); + ) || api_is_drh(); if ($edit == true) { if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) { diff --git a/main/attendance/attendance_sheet.php b/main/attendance/attendance_sheet.php index 7c6fdb4907..d0fe07f7de 100755 --- a/main/attendance/attendance_sheet.php +++ b/main/attendance/attendance_sheet.php @@ -16,7 +16,7 @@ api_protect_course_script(true); $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh( api_get_user_id(), api_get_course_info() -); +) || api_is_drh(); if (api_is_allowed_to_edit(null, true) || api_is_coach(api_get_session_id(), api_get_course_int_id()) || diff --git a/main/gradebook/index.php b/main/gradebook/index.php index 04feeeb673..58a8b91914 100755 --- a/main/gradebook/index.php +++ b/main/gradebook/index.php @@ -786,7 +786,6 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true) } if (api_is_allowed_to_edit(null, true)) { - if (((empty($selectCat)) || (isset($_GET['cidReq']) && $_GET['cidReq'] !== '')) || (isset($_GET['isStudentView']) && $_GET['isStudentView'] == 'false') ) { diff --git a/main/inc/ajax/agenda.ajax.php b/main/inc/ajax/agenda.ajax.php index 390623f605..fdd6164037 100755 --- a/main/inc/ajax/agenda.ajax.php +++ b/main/inc/ajax/agenda.ajax.php @@ -19,6 +19,8 @@ if ($type == 'course') { } $agenda = new Agenda($type); +// get filtered type +$type = $agenda->getType(); switch ($action) { case 'add_event': @@ -26,15 +28,17 @@ switch ($action) { break; } $add_as_announcement = isset($_REQUEST['add_as_annonuncement']) ? $_REQUEST['add_as_annonuncement'] : null; - $comment = isset($_REQUEST['comment']) ? $_REQUEST['comment'] : null; + $title = isset($_REQUEST['title']) ? Security::remove_XSS($_REQUEST['title']) : null; + $content = isset($_REQUEST['content']) ? Security::remove_XSS($_REQUEST['content']) : null; + $comment = isset($_REQUEST['comment']) ? Security::remove_XSS($_REQUEST['comment']) : null; $userToSend = isset($_REQUEST['users_to_send']) ? $_REQUEST['users_to_send'] : []; echo $agenda->addEvent( $_REQUEST['start'], $_REQUEST['end'], $_REQUEST['all_day'], - $_REQUEST['title'], - $_REQUEST['content'], + $title, + $content, $userToSend, $add_as_announcement, null, //$parentEventId = null, @@ -54,8 +58,8 @@ switch ($action) { $_REQUEST['start'], $_REQUEST['end'], $_REQUEST['all_day'], - $_REQUEST['title'], - $_REQUEST['content'] + $title, + $content ); break; case 'delete_event': diff --git a/main/inc/lib/agenda.lib.php b/main/inc/lib/agenda.lib.php index 13ac374840..ce383db97a 100644 --- a/main/inc/lib/agenda.lib.php +++ b/main/inc/lib/agenda.lib.php @@ -160,6 +160,18 @@ class Agenda } } + /** + * Returns the type previously set (and filtered) through setType + * If setType() was not called, then type defaults to "personal" as + * set in the class definition. + */ + public function getType() + { + if (isset($this->type)) { + return $this->type; + } + } + /** * @param int $id */ diff --git a/main/inc/lib/attendance.lib.php b/main/inc/lib/attendance.lib.php index aaa437c451..719e9d8143 100755 --- a/main/inc/lib/attendance.lib.php +++ b/main/inc/lib/attendance.lib.php @@ -154,8 +154,9 @@ class Attendance while ($attendance = Database::fetch_row($res)) { $student_param = ''; - if (api_is_drh() && $_GET['student_id']) { - $student_param = '&student_id='.intval($_GET['student_id']); + $studentRequestId = isset($_GET['student_id']) ? (int) $_GET['student_id'] : 0; + if (api_is_drh() && !empty($studentRequestId)) { + $student_param = '&student_id='.$studentRequestId; } $session_star = ''; @@ -166,8 +167,7 @@ class Attendance $isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh( api_get_user_id(), api_get_course_info() - ); - + ) || api_is_drh(); if (api_is_allowed_to_edit(null, true) || $isDrhOfCourse) { // Link to edit $attendance[1] = ''.$attendance[1].''.$session_star; diff --git a/main/inc/lib/lp_item.lib.php b/main/inc/lib/lp_item.lib.php index d02ac2cf4f..90be7df51c 100755 --- a/main/inc/lib/lp_item.lib.php +++ b/main/inc/lib/lp_item.lib.php @@ -43,10 +43,10 @@ class LpItem { if ($in_c_id > 0 && $in_id > 0) { $item_view_table = Database::get_course_table(TABLE_LP_ITEM); - $sql = "SELECT * FROM $item_view_table - WHERE - c_id=".intval($in_c_id)." AND - id=".intval($in_id); + $sql = "SELECT * FROM $item_view_table + WHERE + c_id=".intval($in_c_id)." AND + iid=".intval($in_id); $res = Database::query($sql); $data = Database::fetch_array($res); @@ -84,27 +84,27 @@ class LpItem { $table = Database::get_course_table(TABLE_LP_ITEM); if ($this->c_id > 0 && $this->id > 0) { - $sql = "UPDATE $table SET - lp_id = '".intval($this->lp_id)."' , - item_type = '".Database::escape_string($this->item_type)."' , - ref = '".Database::escape_string($this->ref)."' , - title = '".Database::escape_string($this->title)."' , - description = '".Database::escape_string($this->description)."' , - path = '".Database::escape_string($this->path)."' , - min_score = '".Database::escape_string($this->min_score)."' , - max_score = '".Database::escape_string($this->max_score)."' , - mastery_score = '".Database::escape_string($this->mastery_score)."' , - parent_item_id = '".Database::escape_string($this->parent_item_id)."' , - previous_item_id = '".Database::escape_string($this->previous_item_id)."' , - next_item_id = '".Database::escape_string($this->next_item_id)."' , - display_order = '".Database::escape_string($this->display_order)."' , - prerequisite = '".Database::escape_string($this->prerequisite)."' , - parameters = '".Database::escape_string($this->parameters)."' , - launch_data = '".Database::escape_string($this->launch_data)."' , - max_time_allowed = '".Database::escape_string($this->max_time_allowed)."' , - terms = '".Database::escape_string($this->terms)."' , - search_did = '".Database::escape_string($this->search_did)."' , - audio = '".Database::escape_string($this->audio)."' + $sql = "UPDATE $table SET + lp_id = '".intval($this->lp_id)."' , + item_type = '".Database::escape_string($this->item_type)."' , + ref = '".Database::escape_string($this->ref)."' , + title = '".Database::escape_string($this->title)."' , + description = '".Database::escape_string($this->description)."' , + path = '".Database::escape_string($this->path)."' , + min_score = '".Database::escape_string($this->min_score)."' , + max_score = '".Database::escape_string($this->max_score)."' , + mastery_score = '".Database::escape_string($this->mastery_score)."' , + parent_item_id = '".Database::escape_string($this->parent_item_id)."' , + previous_item_id = '".Database::escape_string($this->previous_item_id)."' , + next_item_id = '".Database::escape_string($this->next_item_id)."' , + display_order = '".Database::escape_string($this->display_order)."' , + prerequisite = '".Database::escape_string($this->prerequisite)."' , + parameters = '".Database::escape_string($this->parameters)."' , + launch_data = '".Database::escape_string($this->launch_data)."' , + max_time_allowed = '".Database::escape_string($this->max_time_allowed)."' , + terms = '".Database::escape_string($this->terms)."' , + search_did = '".Database::escape_string($this->search_did)."' , + audio = '".Database::escape_string($this->audio)."' WHERE c_id=".$this->c_id." AND id=".$this->id; Database::query($sql); } diff --git a/main/inc/lib/template.lib.php b/main/inc/lib/template.lib.php index d2a87662b7..df822a4c77 100755 --- a/main/inc/lib/template.lib.php +++ b/main/inc/lib/template.lib.php @@ -1916,7 +1916,9 @@ class Template /** * Get platform meta image tag (check meta_image_path setting, then use the logo). + * * @param string $imageAlt The alt attribute for the image + * * @return string The meta image HTML tag, or empty */ private function getMetaPortalImagePath($imageAlt = '') diff --git a/main/inc/lib/tracking.lib.php b/main/inc/lib/tracking.lib.php index f0a788489a..dcac72ab05 100755 --- a/main/inc/lib/tracking.lib.php +++ b/main/inc/lib/tracking.lib.php @@ -7448,8 +7448,9 @@ class TrackingCourseLog $direction, $includeInvitedUsers = false ) { - global $user_ids, $course_code, $export_csv, $csv_content, $session_id; + global $user_ids, $course_code, $export_csv, $session_id; + $csv_content = []; $course_code = Database::escape_string($course_code); $tbl_user = Database::get_main_table(TABLE_MAIN_USER); $tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); @@ -7696,6 +7697,10 @@ class TrackingCourseLog $users[] = array_values($user_row); } + if ($export_csv) { + Session::write('csv_content', $csv_content); + } + Session::erase('additional_user_profile_info'); Session::erase('extra_field_info'); diff --git a/main/lang/brazilian/trad4all.inc.php b/main/lang/brazilian/trad4all.inc.php index ca79d679d2..845f5ae3c3 100644 --- a/main/lang/brazilian/trad4all.inc.php +++ b/main/lang/brazilian/trad4all.inc.php @@ -79,7 +79,7 @@ $HyperbolicArctangentArctanh = "Arco tangente hiperbólica: \t\t arctanh (x)"; $SessionDurationTitle = "Duração da sessão"; $ArctangentArctan = "Arctangent:\t\t\tarctan(x)"; $HyperbolicTangentTanh = "Tangente hiperbólica:\t\ttanh(x)"; -$TangentTan = "Tangent:\t\t\ TTAN (x)"; +$TangentTan = "Tangent:\t\t\tTAN (x)"; $CoachAndStudent = "Treinador e aluno"; $Serie = "Series"; $HyperbolicArccosineArccosh = "Arccosine hiperbólica:\t\tarccosh(x)"; @@ -90,13 +90,13 @@ $TeacherTimeReport = "Professores relatório de tempo"; $HyperbolicArcsineArcsinh = "arcsine hiperbólica:\t\tarcsinh(x)"; $YourLanguageNotThereContactUs = "Não é possível encontrar o seu idioma na lista? Contacte-nos em info@chamilo.org contribuir como um tradutor."; $ArcsineArcsin = "arcsine:\t\t\tarcsin(x)"; -$HyperbolicSineSinh = "Seno hiperbólico:\t\ sinh(x)"; +$HyperbolicSineSinh = "Seno hiperbólico:\t\tsinh(x)"; $SineSin = "Sine:\t\t\t\tsin(x)"; $PiNumberPi = "Número Pi:\t\t\tpi"; $ENumberE = "Número E:\t\t\te"; $LogarithmLog = "Logaritmo:\t\t\tlog(x)"; $NaturalLogarithmLn = "Logaritmo natural:\t\tln(x)"; -$AbsoluteValueAbs = "Valor absoluto:\t\t\abas(x)"; +$AbsoluteValueAbs = "Valor absoluto:\t\t\tabas(x)"; $SquareRootSqrt = "Raiz quadrada:\t\t\tsqrt(x)"; $ExponentiationCircumflex = "Exponenciação:\t\t\t^"; $DivisionSlash = "Divisão:\t\t\t/"; @@ -2348,7 +2348,7 @@ $GroupDescription = "Descrição do grupo"; $GroupMembers = "Membros do grupo"; $EditGroup = "Editar este grupo"; $GroupSettingsModified = "Configurações do grupo modificado"; -$GroupTooMuchMembers = "Número proposta excede max que você permitiu que (você pode modificá-lo abaixo) \ t \ t \ t \ composição tgroup não foi modificado."; +$GroupTooMuchMembers = "Número proposta excede max que você permitiu que (você pode modificá-lo abaixo) \t\t\t\t composição tgroup não foi modificado."; $GroupTutor = "Tutor Grupo"; $GroupNoTutor = "(nenhum)"; $GroupNone = "(nenhum)"; @@ -5934,7 +5934,7 @@ $ContactInformationHasBeenSent = "As informações de contato foram enviadas"; $EditExtraFieldOptions = "Editar opções de campos extra"; $ExerciseDescriptionLabel = "Descrição"; $UserInactivedSinceX = "Usuário inativo desde %s"; -$ContactInformationDescription = "Prezado usuário,
\ n
Você está prestes a começar a usar um dos melhores de fonte aberta plataforma e-learning no mercado. Como muitos outros projetos de código aberto, este projecto é apoiado -se por uma grande comunidade de estudantes, professores, desenvolvedores e criadores de conteúdo que gostariam de promover melhor o projeto.
\n
\nAo saber um pouco mais sobre você, um dos nossos usuários mais importantes, quem vai gerir este chamilo de e-learning, que será capaz de deixar as pessoas sabem que o nosso software é usado e que você saiba quando nós organizamos eventos que possam ser relevantes para você.
\ n
\ nAo enchimento Desta forma, você aceita que a associação Chamilo ou seus membros possam enviar informações por e-mail sobre eventos importantes ou atualizações do software Chamilo ou comunidade. Isto irá ajudar a comunidade a crescer como uma entidade organizada, onde o fluxo de informações, com um respeito permanente de seu tempo e sua privacidade.
\ n
\ nPor favor nota que você é não é necessário para preencher este formulário. Se você quiser permanecer anônimo, vamos perder a oportunidade de oferecer-lhe todos os privilégios de ser um administrador do portal registrado, mas nós vamos respeitar sua decisão. Basta deixar esta forma vazia e clique em \"Avançar\"

."; +$ContactInformationDescription = "Prezado usuário,
\n
Você está prestes a começar a usar um dos melhores de fonte aberta plataforma e-learning no mercado. Como muitos outros projetos de código aberto, este projecto é apoiado -se por uma grande comunidade de estudantes, professores, desenvolvedores e criadores de conteúdo que gostariam de promover melhor o projeto.
\n
\nAo saber um pouco mais sobre você, um dos nossos usuários mais importantes, quem vai gerir este chamilo de e-learning, que será capaz de deixar as pessoas sabem que o nosso software é usado e que você saiba quando nós organizamos eventos que possam ser relevantes para você.
\n
\nAo enchimento Desta forma, você aceita que a associação Chamilo ou seus membros possam enviar informações por e-mail sobre eventos importantes ou atualizações do software Chamilo ou comunidade. Isto irá ajudar a comunidade a crescer como uma entidade organizada, onde o fluxo de informações, com um respeito permanente de seu tempo e sua privacidade.
\n
\nPor favor nota que você é não é necessário para preencher este formulário. Se você quiser permanecer anônimo, vamos perder a oportunidade de oferecer-lhe todos os privilégios de ser um administrador do portal registrado, mas nós vamos respeitar sua decisão. Basta deixar esta forma vazia e clique em \"Avançar\"

."; $CompanyActivity = "atividade da sua empresa"; $PleaseAllowUsALittleTimeToSubscribeYouToOneOfOurCourses = "Por favor, permita-nos um pouco de tempo para se inscrever você para um dos nossos cursos Se você acha que esqueci de você, entre em contato com os administradores do portal normalmente você pode encontrar os detalhes de contato no rodapé desta página..."; $ManageSessionFields = "Gerenciar campos de sessão"; @@ -6124,7 +6124,7 @@ $OnlyAccessFromYourGroup = "Só acessível a partir de seu grupo"; $CreateAssignmentPage = "Isto irá criar uma página wiki especial em que o professor pode descrever a tarefa e que serão ligadas automaticamente para as páginas wiki onde os alunos realizam a tarefa. Tanto o professor e páginas dos alunos são criados automaticamente. Nestas tarefas , os alunos só podem editar e ver DELE páginas, mas isso pode ser mudado facilmente se você precisar."; $UserFolders = "Pastas de usuários"; $UserFolder = "Pasta do usuário"; -$HelpUsersFolder = "informação visível para o professor SOMENTE:.\NA pasta usuários contém uma pasta para cada usuário que acessou-o através da ferramenta de documentos, ou quando qualquer arquivo foi enviado no curso através do editor on-line Se nem circunstâncias ocorreu, em seguida, nenhuma pasta do usuário terá sido criado. No caso de grupos, os arquivos que são enviados através do editor será adicionado na pasta de cada grupo, que só é acessível por estudantes deste grupo.\n

\nOs usuários pasta e cada uma das pastas incluídas ficarão ocultas por padrão no para todos os alunos, mas cada aluno pode ver o conteúdo do seu/sua diretório através do editor online. No entanto, se um estudante conhece o endereço de um arquivo ou pasta de um outro estudante, ele pode ser capaz de acessá-lo.\n

\nSe a pasta de um estudante é visível, outros alunos podem ver o que ele contém. Neste caso, o aluno que possui a pasta pode também (a partir da ferramenta documentos e somente em sua pasta/ela): criar e editar documentos web, converter um documento em um modelo para uso pessoal, criar e editar desenhos em SVG e PNG formatos, arquivos de áudio em formato WAV gravação, faça arquivos de áudio em MP3 a partir de um texto, faça snapshops a partir de uma webcam, enviar documentos, criar pastas, mover pastas e arquivos, excluir pastas e arquivos, e faça o download de backup de sua pasta/ela.\n

\nAlém disso, a ferramenta documentos está sincronizado com o gerente do editor on-line de arquivos, pelo que as alterações nos documentos acionado em qualquer um deles afetará ambos.\n

\nComo tal, a pasta de usuário é não só um lugar para depositar os arquivos, torna-se um gerente completo dos documentos estudantes usam durante o curso. Além disso, lembre-se que qualquer usuário pode copiar um arquivo que é visível a partir de qualquer pasta na ferramenta de documentos (ou não, ele é o proprietário) para seu/sua carteira ou documentos pessoais área de rede social, que estará disponível para ele / ela para uso em outros cursos."; +$HelpUsersFolder = "informação visível para o professor SOMENTE:.\nA pasta usuários contém uma pasta para cada usuário que acessou-o através da ferramenta de documentos, ou quando qualquer arquivo foi enviado no curso através do editor on-line Se nem circunstâncias ocorreu, em seguida, nenhuma pasta do usuário terá sido criado. No caso de grupos, os arquivos que são enviados através do editor será adicionado na pasta de cada grupo, que só é acessível por estudantes deste grupo.\n

\nOs usuários pasta e cada uma das pastas incluídas ficarão ocultas por padrão no para todos os alunos, mas cada aluno pode ver o conteúdo do seu/sua diretório através do editor online. No entanto, se um estudante conhece o endereço de um arquivo ou pasta de um outro estudante, ele pode ser capaz de acessá-lo.\n

\nSe a pasta de um estudante é visível, outros alunos podem ver o que ele contém. Neste caso, o aluno que possui a pasta pode também (a partir da ferramenta documentos e somente em sua pasta/ela): criar e editar documentos web, converter um documento em um modelo para uso pessoal, criar e editar desenhos em SVG e PNG formatos, arquivos de áudio em formato WAV gravação, faça arquivos de áudio em MP3 a partir de um texto, faça snapshops a partir de uma webcam, enviar documentos, criar pastas, mover pastas e arquivos, excluir pastas e arquivos, e faça o download de backup de sua pasta/ela.\n

\nAlém disso, a ferramenta documentos está sincronizado com o gerente do editor on-line de arquivos, pelo que as alterações nos documentos acionado em qualquer um deles afetará ambos.\n

\nComo tal, a pasta de usuário é não só um lugar para depositar os arquivos, torna-se um gerente completo dos documentos estudantes usam durante o curso. Além disso, lembre-se que qualquer usuário pode copiar um arquivo que é visível a partir de qualquer pasta na ferramenta de documentos (ou não, ele é o proprietário) para seu/sua carteira ou documentos pessoais área de rede social, que estará disponível para ele/ela para uso em outros cursos."; $HelpFolderChat = "INFORMAÇÕES VISÍVEL SOMENTE PARA O PROFESSOR: pasta\n Está contém todas as sessões que foram abertas no chat. Embora as sessões de chat pode muitas vezes ser trivial, outros pode ser realmente interessante e digno de ser incorporada como um documento de trabalho adicional. Para fazer isso sem alterar a visibilidade desta pasta, tornar o arquivo visível e vinculá-lo a partir de onde você considerem adequadas. Não é recomendado fazer esta pasta visível a todos."; $HelpFolderCertificates = "Informação visível para o professor SOMENTE:.. Pasta\nEste contém os vários modelos de certificados que foram criados para a ferramenta de classificação não é recomendável fazer esta pasta visível a todos"; $DestinationDirectory = "Pasta de destino"; diff --git a/main/lang/galician/trad4all.inc.php b/main/lang/galician/trad4all.inc.php index f0ef5ef06d..3c240ee427 100644 --- a/main/lang/galician/trad4all.inc.php +++ b/main/lang/galician/trad4all.inc.php @@ -7003,10 +7003,24 @@ $GradebookEnableLockingTitle = "Activar bloqueo de Avaliacións para os profesor $GradebookEnableLockingComment = "Unha vez activada, esta opción permitirá aos profesores bloquear calquera avaliación dentro do seu curso. Isto prohibirá ao profesor calquera modificación posterior dos resultados dos seus alumnos nos recursos usados para esta avaliación: exames, leccións, tarefas, etc. O único rol autorizado a desbloquear unha avaliación é o administrador. O profesor estará informado desta posibilidade ao intentar desbloquear a avaliación. Tanto o bloqueo como o desbloqueo estarán gardados no rexistro de actividades importantes do sistema."; $LdapDescriptionComment = "


I. Configuración LDAP

Editar arquivo main/auth/external_login/ldap.conf.php
-> Editar valores do array $extldap_config

Os parámetros son
-> Para actualizar as correspondencias entre usuario e atributos LDAP, editar o array $extldap_user_correspondance
Os valores do array son <chamilo_field> => >ldap_field>
A estrutura do array está explciada no arquivo main/auth/external_login/ldap.conf.php


II. Activar autenticación LDAP

Editar arquivo main/inc/conf/configuration.php
-> Descomentar as liñas
$extAuthSource["extldap"]["login"] =$_configuration['root_sys'].$_configuration['code_append']."auth/external_login/login.ldap.php";
$extAuthSource["extldap"]["newUser"] =$_configuration['root_sys'].$_configuration['code_append']."auth/external_login/newUser.ldap.php";

N.B. : Os usuarios LDAP empregan os mesmos campos ca os usuarios da plataforma para facer login.
N.B. : A activación LDAP engade un menú Autentificación externa [LDAP] nas páxinas de usuario "engadir ou modificar"."; $ShibbolethMainActivateTitle = "Autenticación Shibboleth"; -$ShibbolethMainActivateComment = "En primeiro lugar, ten que configurar Shibboleth para o seu servidor web. Para configuralo en Chamilo: editar o arquivo main/auth/shibboleth/config/aai.class.php Modificar valores de \$result co nome dos atributos de Shibboleth \$result->unique_id = 'mail'; \$result->firstname = 'cn'; \$result->lastname = 'uid'; \$result->email = 'mail'; \$result->language = '-'; \$result->gender = '-'; \$result->address = '-'; \$result->staff_category = '-'; \$result->home_organization_type = '-'; \$result->home_organization = '-'; \$result->affiliation = '-'; \$result->persistent_id = '-'; ... Ir a Plug-in para engadir o botón 'Shibboleth Login' no seu campus de Chamilo."; +$ShibbolethMainActivateComment = "En primeiro lugar, ten que configurar Shibboleth para o seu servidor web. Para configuralo en Chamilo: editar o arquivo main/auth/shibboleth/config/aai.class.php Modificar valores de $result co nome dos atributos de Shibboleth + +... +Ir a Plug-in para engadir o botón 'Shibboleth Login' no seu campus de Chamilo."; $LdapDescriptionTitle = "Autenticación LDAP"; $FacebookMainActivateTitle = "Autenticación Facebook"; -$FacebookMainActivateComment = "En primeiro lugar, tense que crear unha aplicación de Facebook (ver https://developers.facebook.com/apps) cunha conta de Facebook. Nos parámetros de aplicacións de Facebook, o valor de dirección URL do sitio debe tener \"unha acción = fbconnect\" un parámetro GET (http://mychamilo.com/?action=fbconnect, por ejemplo). Entón, editar o arquivo main/auth/external_login/facebook.conf.php e ingresar en \"appId\" e \"secret\" os valores de \$facebook_config. Ir a Plug-in para engadir un botón configurable \"Facebook Login\" para o campus de Chamilo."; +$FacebookMainActivateComment = "En primeiro lugar, tense que crear unha aplicación de Facebook (ver https://developers.facebook.com/apps) cunha conta de Facebook. Nos parámetros de aplicacións de Facebook, o valor de dirección URL do sitio debe tener \"unha acción = fbconnect\" un parámetro GET (http://mychamilo.com/?action=fbconnect, por ejemplo). Entón, editar o arquivo main/auth/external_login/facebook.conf.php e ingresar en \"appId\" e \"secret\" os valores de $facebook_config. Ir a Plug-in para engadir un botón configurable \"Facebook Login\" para o campus de Chamilo."; $AnnouncementForGroup = "Anuncio para un grupo"; $AllGroups = "Todos os grupos"; $LanguagePriority1Title = "Prioridade do idioma 1"; diff --git a/main/lang/polish/trad4all.inc.php b/main/lang/polish/trad4all.inc.php index 1a96b9bb7a..e4851e113b 100644 --- a/main/lang/polish/trad4all.inc.php +++ b/main/lang/polish/trad4all.inc.php @@ -3458,7 +3458,7 @@ $Preserved = "Chroniony"; $ConfirmUnsubscribe = "Potwierdź usunięcie użytkownika"; $See = "Idź do"; $LastVisits = "Moje ostatnie logowania"; -$IfYouWantToAddManyUsers = "Jeśli chcesz dodać listę użytkowników do szkolenia \t\t\, skontaktuj się z administratorem."; +$IfYouWantToAddManyUsers = "Jeśli chcesz dodać listę użytkowników do szkolenia, skontaktuj się z administratorem."; $PassTooEasy = "to hasło jest zbyt proste. Zobacz przykład poniżej"; $AddedToCourse = "jest już zarejestrowany w kursie"; $UserAlreadyRegistered = "Użytkownik o tej nazwie jest już zarejestrowany w tym kursie."; diff --git a/main/lang/tagalog/trad4all.inc.php b/main/lang/tagalog/trad4all.inc.php index 8fdd4297a0..c12c53edaa 100644 --- a/main/lang/tagalog/trad4all.inc.php +++ b/main/lang/tagalog/trad4all.inc.php @@ -1340,7 +1340,7 @@ $ExamPassX = "Pasado sa minimum na %s"; $ExamFail = "Bagsak"; $ExamTracking = "Pagsusubaybay sa pagsusulit"; $EnableCourseValidation = "Balidasyon ng mga kurso"; -$EnableCourseValidationComment = "Kapag ang tampok na \Balidasyon ng kurso\" ay pinagana, ang isang guro ay hindi maaaring makapaglikha ng isang kurso nang nag-iisa. Siya ay dapat magsulat ng isang kahilingan sa kurso. Ang tagapangasiwa ng platform ay niriripaso ang kahilingan at aaprubahan ito o tatanggihan.
Ang tampok na ito ay umaasa sa 'automated e-mail messaing'; i-set ang Chamilo upang mag-access sa isang server ng email at gumamit ng isang nakatalagang e-mail account."; +$EnableCourseValidationComment = "Kapag ang tampok na 'Balidasyon ng kurso' ay pinagana, ang isang guro ay hindi maaaring makapaglikha ng isang kurso nang nag-iisa. Siya ay dapat magsulat ng isang kahilingan sa kurso. Ang tagapangasiwa ng platform ay niriripaso ang kahilingan at aaprubahan ito o tatanggihan.
Ang tampok na ito ay umaasa sa 'automated e-mail messaing'; i-set ang Chamilo upang mag-access sa isang server ng email at gumamit ng isang nakatalagang e-mail account."; $CourseValidationTermsAndConditionsLink = "Balidasyon ng kurso - isang link sa mga takda at mga kondisyon"; $CourseValidationTermsAndConditionsLinkComment = "Ito ang URL sa \"Mga Takda at Mga Kondisyon\" na dokumento na balido sa pagagawa ng kahilingan sa kurso. Kung ang address ay naitakda rito, ang gumagamit ay dapat basahin at sumang-ayon sa mga takda at mga kondisyon bago ipadala ang isang kahilingan sa kurso.
Kung iyong pagganahin ang module ng \"Mga Takda at Mga Kondisyon\" at kung nais mong gamitin ang URL nito, hayaang walang laman ang setting na ito."; $EnabledSVGTitle = "Lumikha at mag-edit ng mga SVG file"; diff --git a/main/lp/learnpath.class.php b/main/lp/learnpath.class.php index 2bd320c80d..3a03bf6f7b 100755 --- a/main/lp/learnpath.class.php +++ b/main/lp/learnpath.class.php @@ -10332,13 +10332,13 @@ class learnpath $selectedMinScore = []; $selectedMaxScore = []; $masteryScore = []; - while ($row = Database::fetch_array($result)) { - if ($row['id'] == $item_id) { + if ($row['iid'] == $item_id) { $selectedMinScore[$row['prerequisite']] = $row['prerequisite_min_score']; $selectedMaxScore[$row['prerequisite']] = $row['prerequisite_max_score']; - $masteryScore[$row['prerequisite']] = $row['mastery_score']; } + $masteryScore[$row['iid']] = $row['mastery_score']; + $arrLP[] = [ 'id' => $row['iid'], 'item_type' => $row['item_type'], diff --git a/main/survey/reporting.php b/main/survey/reporting.php index 8ce4b1fac0..b9eea6ca35 100755 --- a/main/survey/reporting.php +++ b/main/survey/reporting.php @@ -62,21 +62,13 @@ if (!empty($exportReport) && !empty($format)) { switch ($format) { case 'xls': $filename = 'survey_results_'.$survey_id.'.xlsx'; - $data = SurveyUtil::export_complete_report_xls( - $survey_data, - $filename, - $userId - ); + $data = SurveyUtil::export_complete_report_xls($survey_data, $filename, $userId); exit; break; case 'csv': default: - $data = SurveyUtil::export_complete_report( - $survey_data, - $userId - ); + $data = SurveyUtil::export_complete_report($survey_data, $userId); $filename = 'survey_results_'.$survey_id.'.csv'; - header('Content-type: application/octet-stream'); header('Content-Type: application/force-download'); diff --git a/main/survey/surveyUtil.class.php b/main/survey/surveyUtil.class.php index 7f340a2d88..4536cf02e7 100755 --- a/main/survey/surveyUtil.class.php +++ b/main/survey/surveyUtil.class.php @@ -225,7 +225,7 @@ class SurveyUtil */ public static function handle_reporting_actions($survey_data, $people_filled) { - $action = isset($_GET['action']) ? $_GET['action'] : null; + $action = isset($_GET['action']) ? $_GET['action'] : ''; // Getting the number of question $temp_questions_data = SurveyManager::get_questions($_GET['survey_id']); @@ -243,20 +243,22 @@ class SurveyUtil // Counting the number of questions that are relevant for the reporting $survey_data['number_of_questions'] = count($questions_data); - if ($action == 'questionreport') { - self::display_question_report($survey_data); - } - if ($action == 'userreport') { - self::display_user_report($people_filled, $survey_data); - } - if ($action == 'comparativereport') { - self::display_comparative_report(); - } - if ($action == 'completereport') { - self::display_complete_report($survey_data); - } - if ($action == 'deleteuserreport') { - self::delete_user_report($_GET['survey_id'], $_GET['user']); + switch ($action) { + case 'questionreport': + self::display_question_report($survey_data); + break; + case 'userreport': + self::display_user_report($people_filled, $survey_data); + break; + case 'comparativereport': + self::display_comparative_report(); + break; + case 'completereport': + self::display_complete_report($survey_data); + break; + case 'deleteuserreport': + self::delete_user_report($_GET['survey_id'], $_GET['user']); + break; } } @@ -373,7 +375,7 @@ class SurveyUtil echo ''.PHP_EOL; - } - ?> - + $value) { ?> + + - - + diff --git a/plugin/ims_lti/lang/english.php b/plugin/ims_lti/lang/english.php index a675cf0f5b..80496ef89e 100644 --- a/plugin/ims_lti/lang/english.php +++ b/plugin/ims_lti/lang/english.php @@ -36,3 +36,5 @@ $strings['ShareLauncherPicture'] = 'Share launcher\'s picture'; $strings['NoTool'] = 'Tool not exists'; $strings['ToolAddedOnCourseX'] = 'Tool addeed on course %s.'; $strings['SupportDeppLinkingHelp'] = 'Contact your Tool Provider to verify if Deep Linking support is mandatory'; +$strings['NoAccessToUrl'] = 'No access to URL'; +$strings['LaunchUrlNotFound'] = 'Launch URL not found'; diff --git a/plugin/ims_lti/lang/spanish.php b/plugin/ims_lti/lang/spanish.php index e74433c0e6..08f33b71c9 100644 --- a/plugin/ims_lti/lang/spanish.php +++ b/plugin/ims_lti/lang/spanish.php @@ -36,3 +36,5 @@ $strings['ShareLauncherPicture'] = 'Enviar la foto del usuario'; $strings['NoTool'] = 'La herramienta no existe'; $strings['ToolAddedOnCourseX'] = 'Herramienta agregada en el curso %s.'; $strings['SupportDeppLinkingHelp'] = 'Contacte a su Proveedor de Herramienta para verificar si el soporte a Deep Linking es obligatorio'; +$strings['NoAccessToUrl'] = 'Sin acceso a la URL'; +$strings['LaunchUrlNotFound'] = 'URL de lanzamiento no encontrada'; \ No newline at end of file diff --git a/plugin/ims_lti/src/Form/FrmAdd.php b/plugin/ims_lti/src/Form/FrmAdd.php index db0886a13f..89431b2201 100644 --- a/plugin/ims_lti/src/Form/FrmAdd.php +++ b/plugin/ims_lti/src/Form/FrmAdd.php @@ -43,8 +43,8 @@ class FrmAdd extends FormValidator if (null === $this->baseTool) { $this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true); - $this->addText('consumer_key', $plugin->get_lang('ConsumerKey')); - $this->addText('shared_secret', $plugin->get_lang('SharedSecret')); + $this->addText('consumer_key', $plugin->get_lang('ConsumerKey'), false); + $this->addText('shared_secret', $plugin->get_lang('SharedSecret'), false); } $this->addButtonAdvancedSettings('lti_adv'); @@ -72,8 +72,6 @@ class FrmAdd extends FormValidator $this->addCheckBox('share_picture', null, $plugin->get_lang('ShareLauncherPicture')); $this->addHtml(''); $this->addButtonCreate($plugin->get_lang('AddExternalTool')); - $this->applyFilter('__ALL__', 'Security::remove_XSS'); - $this->applyFilter('__ALL__', 'htmlspecialchars_decode'); $this->applyFilter('__ALL__', 'trim'); } diff --git a/plugin/ims_lti/src/Form/FrmEdit.php b/plugin/ims_lti/src/Form/FrmEdit.php index 14a29e4e01..13dec2525f 100644 --- a/plugin/ims_lti/src/Form/FrmEdit.php +++ b/plugin/ims_lti/src/Form/FrmEdit.php @@ -60,8 +60,8 @@ class FrmEdit extends FormValidator if (null === $parent) { $this->addUrl('launch_url', $plugin->get_lang('LaunchUrl'), true); - $this->addText('consumer_key', $plugin->get_lang('ConsumerKey')); - $this->addText('shared_secret', $plugin->get_lang('SharedSecret')); + $this->addText('consumer_key', $plugin->get_lang('ConsumerKey'), false); + $this->addText('shared_secret', $plugin->get_lang('SharedSecret'), false); } $this->addButtonAdvancedSettings('lti_adv'); @@ -91,8 +91,6 @@ class FrmEdit extends FormValidator $this->addButtonUpdate($plugin->get_lang('EditExternalTool')); $this->addHidden('id', $this->tool->getId()); $this->addHidden('action', 'edit'); - $this->applyFilter('__ALL__', 'Security::remove_XSS'); - $this->applyFilter('__ALL__', 'htmlspecialchars_decode'); $this->applyFilter('__ALL__', 'trim'); } diff --git a/plugin/ims_lti/start.php b/plugin/ims_lti/start.php index 70dd2fcb94..a8d78b2b09 100644 --- a/plugin/ims_lti/start.php +++ b/plugin/ims_lti/start.php @@ -18,7 +18,9 @@ if (!$tool) { $imsLtiPlugin = ImsLtiPlugin::create(); -$template = new Template($tool->getName()); +$pageTitle = Security::remove_XSS($tool->getName()); + +$template = new Template($pageTitle); $template->assign('tool', $tool); $template->assign( 'launch_url', @@ -27,6 +29,6 @@ $template->assign( $content = $template->fetch('ims_lti/view/start.tpl'); -$template->assign('header', $tool->getName()); +$template->assign('header', $pageTitle); $template->assign('content', $content); $template->display_one_col_template(); diff --git a/plugin/ims_lti/vendor/oauth1/.gitignore b/plugin/ims_lti/vendor/oauth1/.gitignore new file mode 100644 index 0000000000..ef6021df97 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/.gitignore @@ -0,0 +1,42 @@ + +# Created by https://www.gitignore.io/api/osx,svn,composer + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### SVN ### +.svn/ + + +### Composer ### +composer.phar +/vendor/ + +# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock + diff --git a/plugin/ims_lti/vendor/oauth1/CHANGELOG.md b/plugin/ims_lti/vendor/oauth1/CHANGELOG.md new file mode 100644 index 0000000000..f4fb067a2a --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/CHANGELOG.md @@ -0,0 +1,44 @@ +### 2016.02.10 +---- +* Added composer.json +* Separated classes to separate files + +### 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](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](http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226) +* Fixed a small bug per: + [https://github.com/jtsternberg/oauth/issues/26](https://github.com/jtsternberg/oauth/issues/26) +* Added missing base_string debug info when using RSA-SHA1 +* Increased size of example endpoint input field and added note about + query strings + +### 2009-2011.03.28 +---- +* Heaps of bug-fixes +* Introduction of PHPUnit testcases (which aided in above mentioned bug-fixes) +* Added support Revision A auth flows. +* Possibly more, I've lost track.. + +### 2001.03.29 +---- +* Fixed issue with hosts not being normalized correctly + [http://tools.ietf.org/html/rfc5849#section-3.4.1.2](http://tools.ietf.org/html/rfc5849#section-3.4.1.2) + [https://github.com/jtsternberg/oauth/issues/176](https://github.com/jtsternberg/oauth/issues/176) + [https://github.com/jtsternberg/oauth/issues/187](https://github.com/jtsternberg/oauth/issues/187) +* Changed signature comparing to be timing insensitive + [https://github.com/jtsternberg/oauth/issues/178](https://github.com/jtsternberg/oauth/issues/178) +* Fixed issue with Host header on some servers on non-standard port includes the port-number + [https://github.com/jtsternberg/oauth/issues/170](https://github.com/jtsternberg/oauth/issues/170) + [https://github.com/jtsternberg/oauth/issues/192](https://github.com/jtsternberg/oauth/issues/192) diff --git a/plugin/ims_lti/vendor/oauth1/LICENSE.txt b/plugin/ims_lti/vendor/oauth1/LICENSE.txt new file mode 100644 index 0000000000..89f0591697 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/README.md b/plugin/ims_lti/vendor/oauth1/README.md new file mode 100644 index 0000000000..7799d0bbac --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/README.md @@ -0,0 +1,6 @@ +# OAuth1 PHP +[Andy Smith](http://term.ie/)'s basic php library for OAuth. Original code taken from google code. For reference (and since google code is going away), I have ported the entire project to github. [You can find it here](https://github.com/jtsternberg/oauth). + +To use this, be sure to run `composer install` in the root of the lib. + +I have also split out the spec portion of the google code repo to [its own repo](https://github.com/jtsternberg/oauth-spec). diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthConsumer.php b/plugin/ims_lti/vendor/oauth1/code/OAuthConsumer.php new file mode 100644 index 0000000000..dde0cb2ee0 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthConsumer.php @@ -0,0 +1,16 @@ +key = $key; + $this->secret = $secret; + $this->callback_url = $callback_url; + } + + function __toString() { + return "OAuthConsumer[key=$this->key,secret=$this->secret]"; + } +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthDataStore.php b/plugin/ims_lti/vendor/oauth1/code/OAuthDataStore.php new file mode 100644 index 0000000000..a1d04055ca --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthDataStore.php @@ -0,0 +1,27 @@ +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 = ($http_url) ? $http_url : $scheme . + '://' . $_SERVER['SERVER_NAME'] . + ':' . + $_SERVER['SERVER_PORT'] . + $_SERVER['REQUEST_URI']; + $http_method = ($http_method) ? $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" + && isset($request_headers['Content-Type']) + && 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 (isset($request_headers['Authorization']) && 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 = ($parameters) ? $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); + + $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; + $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80'); + $host = (isset($parts['host'])) ? strtolower($parts['host']) : ''; + $path = (isset($parts['path'])) ? $parts['path'] : ''; + + 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 + } +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthServer.php b/plugin/ims_lti/vendor/oauth1/code/OAuthServer.php new file mode 100644 index 0000000000..f0a8f0e006 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthServer.php @@ -0,0 +1,223 @@ +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 instanceof OAuthRequest + ? $request->get_parameter("oauth_signature_method") + : NULL; + + 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 instanceof OAuthRequest + ? $request->get_parameter("oauth_consumer_key") + : NULL; + + 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 instanceof OAuthRequest + ? $request->get_parameter('oauth_token') + : NULL; + + $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 instanceof OAuthRequest + ? $request->get_parameter('oauth_timestamp') + : NULL; + $nonce = $request instanceof OAuthRequest + ? $request->get_parameter('oauth_nonce') + : NULL; + + $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"); + } + } + +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod.php b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod.php new file mode 100644 index 0000000000..ea7adc16f7 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod.php @@ -0,0 +1,55 @@ +build_signature($request, $consumer, $token); + + // Check for zero length, although unlikely here + if (strlen($built) == 0 || strlen($signature) == 0) { + return false; + } + + if (strlen($built) != strlen($signature)) { + return false; + } + + // Avoid a timing leak with a (hopefully) time insensitive compare + $result = 0; + for ($i = 0; $i < strlen($signature); $i++) { + $result |= ord($built{$i}) ^ ord($signature{$i}); + } + + return $result == 0; + } +} + diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_HMAC_SHA1.php b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_HMAC_SHA1.php new file mode 100644 index 0000000000..8ec32d6a7a --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_HMAC_SHA1.php @@ -0,0 +1,30 @@ +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)); + } +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_PLAINTEXT.php b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_PLAINTEXT.php new file mode 100644 index 0000000000..4053ec2c9f --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_PLAINTEXT.php @@ -0,0 +1,34 @@ +secret, + ($token) ? $token->secret : "" + ); + + $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); + $key = implode('&', $key_parts); + $request->base_string = $key; + + return $key; + } +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_RSA_SHA1.php b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_RSA_SHA1.php new file mode 100644 index 0000000000..41474ef614 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthSignatureMethod_RSA_SHA1.php @@ -0,0 +1,69 @@ +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; + } +} + diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthTests.xml b/plugin/ims_lti/vendor/oauth1/code/OAuthTests.xml new file mode 100644 index 0000000000..39122a1b39 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthTests.xml @@ -0,0 +1,13 @@ + + + tests + + + + tests + + + + + + \ No newline at end of file diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthToken.php b/plugin/ims_lti/vendor/oauth1/code/OAuthToken.php new file mode 100644 index 0000000000..1fc1431515 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthToken.php @@ -0,0 +1,31 @@ +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(); + } +} diff --git a/plugin/ims_lti/vendor/oauth1/code/OAuthUtil.php b/plugin/ims_lti/vendor/oauth1/code/OAuthUtil.php new file mode 100644 index 0000000000..bef292de04 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/OAuthUtil.php @@ -0,0 +1,153 @@ + $h) { + $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]); + } + 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) + // June 12th, 2010 - changed to sort because of issue 164 by hidetaka + sort($value, SORT_STRING); + 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/plugin/ims_lti/vendor/oauth1/code/OAuth_TestServer.php b/plugin/ims_lti/vendor/oauth1/code/OAuth_TestServer.php new file mode 100644 index 0000000000..1119eab29c --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/code/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/plugin/ims_lti/vendor/oauth1/composer.json b/plugin/ims_lti/vendor/oauth1/composer.json new file mode 100644 index 0000000000..16c0b2af4f --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/composer.json @@ -0,0 +1,30 @@ +{ + "name": "jtsternberg/oauth1-php", + "description": "Andy Smith's basic php library for OAuth.", + "license": "MIT", + "authors": [ + { + "name": "Andy Smith", + "homepage": "http://term.ie/", + "role": "Developer" + }, + { + "name": "Justin Sternberg", + "email": "justin@dsgnwrks.pro", + "homepage": "https://dsgnwrks.pro", + "role": "Developer" + } + ], + "keywords": ["oauth", "oauth1", "php"], + "homepage": "https://github.com/jtsternberg/oauth1-php", + "support": { + "issues": "https://github.com/jtsternberg/oauth1-php/issues", + "source": "https://github.com/jtsternberg/oauth1-php" + }, + "require": { + "php": ">5.3" + }, + "autoload": { + "classmap": ["code"] + } +} diff --git a/plugin/ims_lti/vendor/oauth1/composer.lock b/plugin/ims_lti/vendor/oauth1/composer.lock new file mode 100644 index 0000000000..3dff17e737 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/composer.lock @@ -0,0 +1,20 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "9ec16f80a40b9ed7b9501632e2ab33c3", + "content-hash": "17d848aa0b54718b6bf5334fd7e94bcc", + "packages": [], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">5.3" + }, + "platform-dev": [] +} diff --git a/plugin/ims_lti/vendor/oauth1/doc/design.md b/plugin/ims_lti/vendor/oauth1/doc/design.md new file mode 100644 index 0000000000..fcea80bd99 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/doc/design.md @@ -0,0 +1,73 @@ +## 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/plugin/ims_lti/vendor/oauth1/example/SimpleOAuthDataStore.php b/plugin/ims_lti/vendor/oauth1/example/SimpleOAuthDataStore.php new file mode 100644 index 0000000000..98474d6543 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/example/access_token.php b/plugin/ims_lti/vendor/oauth1/example/access_token.php new file mode 100644 index 0000000000..737a64485c --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/example/client.php b/plugin/ims_lti/vendor/oauth1/example/client.php new file mode 100644 index 0000000000..5c5ab6344f --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/example/common.inc.php b/plugin/ims_lti/vendor/oauth1/example/common.inc.php new file mode 100644 index 0000000000..39a7c4de4d --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/example/common.inc.php @@ -0,0 +1,26 @@ +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/plugin/ims_lti/vendor/oauth1/example/echo_api.php b/plugin/ims_lti/vendor/oauth1/example/echo_api.php new file mode 100644 index 0000000000..a79173f268 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/example/index.php b/plugin/ims_lti/vendor/oauth1/example/index.php new file mode 100644 index 0000000000..11feacadbe --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/example/request_token.php b/plugin/ims_lti/vendor/oauth1/example/request_token.php new file mode 100644 index 0000000000..f6c02f488e --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/init.php b/plugin/ims_lti/vendor/oauth1/init.php new file mode 100644 index 0000000000..c744d7491a --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/init.php @@ -0,0 +1,5 @@ +provided_base_string = $bs; } + public function get_signature_base_string() { return $this->provided_base_string; } +} diff --git a/plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthDataStore.php b/plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthDataStore.php new file mode 100644 index 0000000000..cd50e97901 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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, $callback = null) { + if ($consumer->key == $this->consumer->key) { + return $this->request_token; + } + return NULL; + } + + function new_access_token($token, $consumer, $verifier = null) { + 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/plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php b/plugin/ims_lti/vendor/oauth1/tests/Mock_OAuthSignatureMethod_RSA_SHA1.php new file mode 100644 index 0000000000..aa893c8ec7 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthRequestTest.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthRequestTest.php new file mode 100644 index 0000000000..83e2c5b3cf --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/tests/OAuthRequestTest.php @@ -0,0 +1,329 @@ +'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()); + + OAuthTestUtils::build_request('POST', 'http://Example.COM'); + $this->assertEquals('http://example.com', OAuthRequest::from_request()->get_normalized_http_url()); + + // Emulate silly behavior by some clients, where there Host header includes the port + OAuthTestUtils::build_request('POST', 'http://example.com'); + $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT']; + $this->assertEquals('http://example.com', 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')); + + OAuthTestUtils::build_request('POST', 'http://example.com', 'oauth_test=foo'); + $this->assertEquals('Authorization: OAuth oauth_test="foo"', OAuthRequest::from_request()->to_header()); + $this->assertEquals('Authorization: OAuth realm="test",oauth_test="foo"', 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/plugin/ims_lti/vendor/oauth1/tests/OAuthServerTest.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthServerTest.php new file mode 100644 index 0000000000..d4d1192f8e --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodHmacSha1Test.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodHmacSha1Test.php new file mode 100644 index 0000000000..3d5cc7524a --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodPlaintextTest.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodPlaintextTest.php new file mode 100644 index 0000000000..d096243313 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodRsaSha1Test.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthSignatureMethodRsaSha1Test.php new file mode 100644 index 0000000000..74e5037734 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthTokenTest.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthTokenTest.php new file mode 100644 index 0000000000..20d8113af7 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/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/plugin/ims_lti/vendor/oauth1/tests/OAuthUtilTest.php b/plugin/ims_lti/vendor/oauth1/tests/OAuthUtilTest.php new file mode 100644 index 0000000000..072c9facd2 --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/tests/OAuthUtilTest.php @@ -0,0 +1,151 @@ +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'))) + ); + + // From issue 164, by hidetaka + // Based on discussion at + // http://groups.google.com/group/oauth/browse_thread/thread/7c698004be0d536/dced7b6c82b917b2?lnk=gst&q=sort# + $this->assertEquals( + 'x=200&x=25&y=B&y=a', + OAuthUtil::build_http_query(array('x'=>array(25, 200), 'y'=>array('a', 'B'))) + ); + } + + 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() ); + + // Test picking up the Content-Type of POST requests running as an Apache module but not having the ARH method + $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + $this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar', 'Content-Type'=>'application/x-www-form-urlencoded'), OAuthUtil::get_headers() ); + + // Test picking up the Content-Type of POST requests when using CGI + unset($_SERVER['CONTENT_TYPE']); + $this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar'), OAuthUtil::get_headers() ); + $_ENV['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + $this->assertEquals( array('Host'=>'foo', 'X-Whatever'=>'bar', 'Content-Type'=>'application/x-www-form-urlencoded'), OAuthUtil::get_headers() ); + } +} diff --git a/plugin/ims_lti/vendor/oauth1/tests/common.php b/plugin/ims_lti/vendor/oauth1/tests/common.php new file mode 100644 index 0000000000..9d789c9cab --- /dev/null +++ b/plugin/ims_lti/vendor/oauth1/tests/common.php @@ -0,0 +1,60 @@ + - {{ tool.name }} + {{ tool.name|e }} {% endfor %} @@ -46,7 +46,7 @@ {% endif %} - {{ tool.name }} + {{ tool.name|e }} {% endfor %} diff --git a/plugin/ims_lti/view/admin.tpl b/plugin/ims_lti/view/admin.tpl index 569f652559..b731e668b4 100644 --- a/plugin/ims_lti/view/admin.tpl +++ b/plugin/ims_lti/view/admin.tpl @@ -1,43 +1,45 @@ -{{ 'ImsLtiDescription'|get_plugin_lang('ImsLtiPlugin') }} - -
- - - - - - - - - - - {% for tool in tools %} +{% autoescape 'html' %} + {{ 'ImsLtiDescription'|get_plugin_lang('ImsLtiPlugin') }} + +
+
{{ 'Name'|get_lang }}{{ 'LaunchUrl'|get_plugin_lang('ImsLtiPlugin') }}{{ 'IsGlobal'|get_plugin_lang('ImsLtiPlugin') }}{{ 'Actions'|get_lang }}
+ - - - - + + + + - {% endfor %} - -
{{ tool.name }}{{ tool.launchUrl }} - {% if tool.isGlobal %} - - {{ 'Yes'|get_lang }} - {% else %} - - {{ 'No'|get_lang }} - {% endif %} - - - {{ 'Edit'|get_lang }} - - - {{ 'Delete'|get_lang }} - - {{ 'Name'|get_lang }}{{ 'LaunchUrl'|get_plugin_lang('ImsLtiPlugin') }}{{ 'IsGlobal'|get_plugin_lang('ImsLtiPlugin') }}{{ 'Actions'|get_lang }}
-
+ + + {% for tool in tools %} + + {{ tool.name }} + {{ tool.launchUrl }} + + {% if tool.isGlobal %} + + {{ 'Yes'|get_lang }} + {% else %} + + {{ 'No'|get_lang }} + {% endif %} + + + + {{ 'Edit'|get_lang }} + + + {{ 'Delete'|get_lang }} + + + + {% endfor %} + + + +{% endautoescape %} diff --git a/plugin/ims_lti/view/start.tpl b/plugin/ims_lti/view/start.tpl index a8c13a39fa..0bcc1c5d13 100644 --- a/plugin/ims_lti/view/start.tpl +++ b/plugin/ims_lti/view/start.tpl @@ -1,5 +1,5 @@ {% if tool.description %} -

{{ tool.description|nl2br }}

+

{{ tool.description|e|nl2br }}

{% endif %}