Skip to content
This repository was archived by the owner on Nov 7, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 infixint943
Copyright (c) 2020 cp-tools

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
<br />
Don't forget to :star: the project if you liked it!
<br /><br />
<a href="https://travis-ci.com/github/infixint943/cf"><img src="https://img.shields.io/travis/com/infixint943/cf?style=for-the-badge"></a>
<a href="https://github.com/infixint943/cf/commits/master"><img src="https://img.shields.io/github/last-commit/infixint943/cf?style=for-the-badge"></a>
<a href="https://github.com/infixint943/cf/releases"><img src="https://img.shields.io/github/v/release/infixint943/cf?style=for-the-badge"></a>
<a href="https://github.com/infixint943/cf/issues"><img src="https://img.shields.io/github/issues/infixint943/cf?style=for-the-badge"></a>
<a href=""><img src="https://img.shields.io/github/go-mod/go-version/infixint943/cf?style=for-the-badge"></a>
<a href="https://github.com/infixint943/cf/blob/master/LICENSE"><img src="https://img.shields.io/github/license/infixint943/cf?style=for-the-badge"></a>
<a href="https://travis-ci.com/github/cp-tools/cf"><img src="https://img.shields.io/travis/com/cp-tools/cf?style=for-the-badge"></a>
<a href="https://github.com/cp-tools/cf/commits/master"><img src="https://img.shields.io/github/last-commit/cp-tools/cf?style=for-the-badge"></a>
<a href="https://github.com/cp-tools/cf/releases"><img src="https://img.shields.io/github/v/release/cp-tools/cf?style=for-the-badge"></a>
<a href="https://github.com/cp-tools/cf/issues"><img src="https://img.shields.io/github/issues/cp-tools/cf?style=for-the-badge"></a>
<a href=""><img src="https://img.shields.io/github/go-mod/go-version/cp-tools/cf?style=for-the-badge"></a>
<a href="https://github.com/cp-tools/cf/blob/master/LICENSE"><img src="https://img.shields.io/github/license/cp-tools/cf?style=for-the-badge"></a>
</h4>


Expand All @@ -37,20 +37,20 @@

# Installation

You may download the latest, compiled, binary files from [here](https://github.com/infixint943/cf/releases).
You may download the latest, compiled, binary files from [here](https://github.com/cp-tools/cf/releases).
Place the executable in system **PATH** to invoke the tool from any directory.

Alternatively, you can also compile the tool from source.

```bash
git clone https://github.com/infixint943/cf.git
git clone https://github.com/cp-tools/cf.git
cd cf/
go build -ldflags "-s -w"
```

# Quick Start

**Note:** For detailed documentation, please head to the [wiki](https://github.com/infixint943/cf/wiki) page.
**Note:** For detailed documentation, please head to the [wiki](https://github.com/cp-tools/cf/wiki) page.

> Let's simulate participating in contest `4`. This tutorial assumes you have already configured your login details and added at least one template, through `cf config`

Expand Down
45 changes: 31 additions & 14 deletions client/fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cln

import (
cfg "cf/config"
pkg "cf/packages"

"bytes"
"fmt"
Expand All @@ -13,19 +12,24 @@ import (
"github.com/PuerkitoBio/goquery"
)

// FindCountdown parses countdown (if exists) from countdown page
/*
FindCountdown parses and returns number of seconds remaining
before contest begins. Returns 0 if countdown has already ended.
Virtual contests (of the current user session) are supported too.

If countdown page doesn't exsit, returns error ErrContestNotExists
*/
func FindCountdown(contest string, link url.URL) (int64, error) {
// This implementation contains redirection prevention
c := cfg.Session.Client
c.CheckRedirect = pkg.RedirectCheck
c.CheckRedirect = redirectCheck
link.Path = path.Join(link.Path, "countdown")
body, err := pkg.GetReqBody(&c, link.String())
body, err := getReqBody(&c, link.String())
if err != nil {
return 0, err
} else if len(body) == 0 {
// such page doesn't exist
err = fmt.Errorf("Contest %v doesn't exist", contest)
return 0, err
return 0, ErrContestNotExists
}

doc, _ := goquery.NewDocumentFromReader(bytes.NewReader(body))
Expand All @@ -36,11 +40,17 @@ func FindCountdown(contest string, link url.URL) (int64, error) {
return h*3600 + m*60 + s, nil
}

// FetchProbs finds all problems present in the contest
/*
FetchProbs parses and returns problem code's of all problems in contest.
Problem codes are returned in their lowercase versions. For example,
A => a, F1 => f1, C2 => c2 etc.

If contest dashboard doesn't exist, returns error ErrContestNotExists
*/
func FetchProbs(contest string, link url.URL) ([]string, error) {
// no need of modifying link as it already points to dashboard
c := cfg.Session.Client
body, err := pkg.GetReqBody(&c, link.String())
body, err := getReqBody(&c, link.String())
if err != nil {
return nil, err
}
Expand All @@ -54,11 +64,18 @@ func FetchProbs(contest string, link url.URL) ([]string, error) {
return probs, nil
}

// FetchTests extracts test cases of the problem(s) in contest
// Returns 2d slice mapping to input and output
// If problem == "", fetch all problem test cases
// else, only fetch of given problem.
// fix for https://github.com/infixint943/cf/pull/2#issuecomment-626122011
/*
FetchTests parses test cases of problems in the contest and returns
the sample inputs/outputs as a 2d slice of strings.

If problem parameter is empty, returns test cases of ALL problems in contest.
Samples are fetched from the contest's 'complete problemset' page.

Otherwise, sample tests of only the specified problem is returned
Here, samples are fetched from the (individual) problem's page

If problems page doesn't exist, returns error ErrContestNotExists
*/
func FetchTests(contest, problem string, link url.URL) ([][]string, [][]string, error) {

c := cfg.Session.Client
Expand All @@ -70,7 +87,7 @@ func FetchTests(contest, problem string, link url.URL) ([][]string, [][]string,
link.Path = path.Join(link.Path, "problem", problem)
}

body, err := pkg.GetReqBody(&c, link.String())
body, err := getReqBody(&c, link.String())
if err != nil {
return nil, nil, err
}
Expand Down
105 changes: 0 additions & 105 deletions client/langs.go

This file was deleted.

47 changes: 32 additions & 15 deletions client/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@ package cln

import (
cfg "cf/config"
pkg "cf/packages"

"encoding/hex"
"fmt"
"net/url"
"path"

"github.com/infixint943/cookiejar"
"github.com/oleiade/serrure/aes"
)

// Login tries logginging in with user creds
/*
Login attempts logging in to configured host domain
with user credentials passed in the parameters.

Returns true if login was successful (saves session to sessPath)
and false if login failed due to wrong credentials.

If login failed for any other reason (other than wrong creds)
the respective hhtp error message is returned.
*/
func Login(usr, passwd string) (bool, error) {
// instantiate http client, but remove
// past user sessions to prevent redirection
Expand All @@ -23,18 +30,18 @@ func Login(usr, passwd string) (bool, error) {

link, _ := url.Parse(cfg.Settings.Host)
link.Path = path.Join(link.Path, "enter")
body, err := pkg.GetReqBody(&c, link.String())
body, err := getReqBody(&c, link.String())
if err != nil {
return false, err
}

// Hidden form data
csrf := pkg.FindCsrf(body)
csrf := findCsrf(body)
ftaa := "yzo0kk4bhlbaw83g2q"
bfaa := "883b704dbe5c70e1e61de4d8aff2da32"

// Post form (aka login using creds)
body, err = pkg.PostReqBody(&c, link.String(), url.Values{
body, err = postReqBody(&c, link.String(), url.Values{
"csrf_token": {csrf},
"action": {"enter"},
"ftaa": {ftaa},
Expand All @@ -48,7 +55,7 @@ func Login(usr, passwd string) (bool, error) {
return false, err
}

usr = pkg.FindHandle(body)
usr = findHandle(body)
if usr != "" {
// create aes 256 encryption and encode as
// hex string and save to sessions.json
Expand All @@ -64,28 +71,38 @@ func Login(usr, passwd string) (bool, error) {
return (usr != ""), nil
}

// LoggedInUsr checks and returns whether
// current session is logged in
/*
LoggedInUsr returns handle of currently logged in user
Session uses Session.Client data to pull homepage
and extract the handle of the logged in user.
Returns an empty string if no logged in user is found

If http request failed, corresponding error is returned
*/
func LoggedInUsr() (string, error) {
// fetch home page and check if logged in
c := cfg.Session.Client
link, _ := url.Parse(cfg.Settings.Host)
body, err := pkg.GetReqBody(&c, link.String())
body, err := getReqBody(&c, link.String())
if err != nil {
return "", err
}

return pkg.FindHandle(body), nil
return findHandle(body), nil
}

// Relogin extracts handle/passwd from sessions.json
// and log's in with the credentials and returns status
/*
Relogin extracts user handle / passwd from the Session struct
and passes the credentials to function Login() to relogin again.
Returns same return values of function Login()

If password couldn't be decrypted, returns error ErrDecodePasswdFailed
*/
func Relogin() (bool, error) {
// decode hex data of encrypted password
ciphertext, err := hex.DecodeString(cfg.Session.Passwd)
if err != nil {
err := fmt.Errorf("Failed to decode password")
return false, err
return false, ErrDecodePasswdFailed
}
usr := cfg.Session.Handle
dec := aes.NewAES256Decrypter(usr)
Expand Down
Loading