import React from 'react';
import {
- StyleSheet, Text, View, TextInput,
- Image,
- Button,
+ StyleSheet, Text, View, TextInput,
+ Image,
+ Button,
} from 'react-native';
import {
- grok_set_url,
- grok_login1,
- grok_login2,
+ grok_set_url,
+ grok_login1,
+ grok_login2,
+ grok_url,
} from './grok.js';
import logo from './assets/images/logo.png';
+import $ from 'jquery';
export default class App extends React.Component {
-
+
state = {
- username: '',
- password: '',
- message: '...',
+ username: '',
+ password: '',
+ message: '...',
+ server: grok_url,
};
constructor(props) {
- super(props);
+ super(props);
};
- handle_login1(login1) {
- ui_login_show_message("Logging in...");
- grok_login2(
- this.handle_login2,
- login1['auth'],
- this.state.username,
- this.state.password,
- )
- }
-
start_login() {
- console.log('Start login!');
- console.log(this.state);
- this.setState({
- message: 'Connecting...',
+ console.log('Start login!');
+ console.log(this.state);
+ this.setState({
+ message: 'Connecting...',
+ });
+
+ grok_set_url(this.state.server);
+
+ grok_login1(this.handle_login1)
+ .then((login1) => {
+
+ this.ui_login_show_message("Logging in...");
+
+ grok_login2(
+ this.handle_login2,
+ login1['auth'],
+ this.state.username,
+ this.state.password,
+ login1['cookies'],
+ ).then(() => {
+ this.ui_login_show_message("Success!");
+ }).catch((error) => {
+ this.ui_login_show_message(error);
+ });
+ }
+ ).catch((error) => {
+ this.ui_login_show_message(error);
});
- grok_login1(this.handle_login1);
};
ui_login_show_message(message) {
};
render() {
- return (
- <View style={styles.container}>
+ return (
+ <View style={styles.container}>
- <View style={styles.innerBox}>
- <Image source={logo} style={styles.logo} />
+ <View style={styles.innerBox}>
+ <Image source={logo} style={styles.logo} />
- <Text>Welcome to dwim!</Text>
+ <Text>Welcome to dwim!</Text>
- <Text>Username:</Text>
+ <Text>Username:</Text>
<TextInput type="text" name="username"
- onChangeText={(text) => { this.state.username = text} }
- style={styles.input}
- />
+ onChangeText={(text) => { this.state.username = text} }
+ style={styles.input}
+ />
- <Text>Password:</Text>
+ <Text>Password:</Text>
<TextInput type="password" name="password"
- onChangeText={(text) => { this.state.password = text} }
- secureTextEntry={true}
- style={styles.input}
- />
-
- <Button
- onPress={() => this.start_login()}
- style={styles.button}
- title="Log in"
- />
-
- <Text
- name="login_message"
- style={styles.login_message}> {this.state.message} </Text>
- </View>
- </View>
- );
- }
+ onChangeText={(text) => { this.state.password = text} }
+ secureTextEntry={true}
+ style={styles.input}
+ />
+
+ <Button
+ onPress={() => this.start_login()}
+ style={styles.button}
+ title="Log in"
+ />
+
+ <Text
+ name="login_message"
+ style={styles.login_message}> {this.state.message} </Text>
+
+ <Text>Server (for debugging):</Text>
+ <TextInput type="text" name="server"
+ onChangeText={(text) => { this.state.server = text} }
+ style={styles.input}
+ value={grok_url}
+ />
+
+ </View>
+ </View>
+ );
+ }
}
const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: '#8a0000',
- alignItems: 'center',
- justifyContent: 'center',
- },
- innerBox: {
- flex: 1,
- backgroundColor: '#fffdd0',
- alignItems: 'center',
- justifyContent: 'center',
- borderRadius: 10,
- width: '70%',
- height: '50%',
- },
- logo: {
- marginBottom: 10,
- },
- input: {
- height: 40,
- margin: 12,
- borderWidth: 1,
- padding: 10,
- width: '80%',
- },
- button: {
- height: 40,
- width: "50%",
- margin: 12,
- borderWidth: 1,
- borderRadius: 5,
- padding: 20,
- backgroundColor: "#8a0000",
- fontSize: 20,
- color: '#fff',
- },
- login_message: {
- fontWeight: "bold",
- fontSize: 14,
- marginTop: 20,
- color: '#000',
- },
+ container: {
+ flex: 1,
+ backgroundColor: '#8a0000',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ innerBox: {
+ flex: 1,
+ backgroundColor: '#fffdd0',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 10,
+ width: '70%',
+ height: '50%',
+ },
+ logo: {
+ marginBottom: 10,
+ },
+ input: {
+ height: 40,
+ margin: 12,
+ borderWidth: 1,
+ padding: 10,
+ width: '80%',
+ },
+ button: {
+ height: 40,
+ width: "50%",
+ margin: 12,
+ borderWidth: 1,
+ borderRadius: 5,
+ padding: 20,
+ backgroundColor: "#8a0000",
+ fontSize: 20,
+ color: '#fff',
+ },
+ login_message: {
+ fontWeight: "bold",
+ fontSize: 14,
+ marginTop: 20,
+ color: '#000',
+ },
});
import React from 'react';
import {
- SafeAreaView,
- StyleSheet,
- View,
- TouchableOpacity,
- Text,
+ SafeAreaView,
+ StyleSheet,
+ View,
+ TouchableOpacity,
+ Text,
} from 'react-native';
-var DREAMWIDTH_URL = 'https://dreamwidth.org';
+import * as SecureStore from 'expo-secure-store';
+import tough from 'tough-cookie';
+import $ from 'jquery';
+
+///////////////////////////////////////
+
+//var DREAMWIDTH_URL = 'https://dreamwidth.org';
+var DREAMWIDTH_URL = 'http://aspidistra:6887'; // FIXME temporary
+
export var grok_url = DREAMWIDTH_URL;
-export function grok_set_url(url) {
- console.log("Requests will go to: "+url);
- grok_url = url;
-}
+///////////////////////////////////////
+
+async function cookie_string(response) {
-function set_cookies(url, response) {
+ var cookies;
- var cookies;
+ console.log('Setting cookies from: '+response);
- console.log('Setting cookies from: ');
- console.log(response);
+ if (!response.headers['set-cookie']) {
+ console.log(" -- no cookies to set");
+ return;
+ }
- for (var h of response.headers) {
- console.log(" -- "+h+" = "+response.headers[h]);
- }
+ if (response.headers['set-cookie'] instanceof Array)
+ cookies = response.headers['set-cookie'].map(Cookie.parse);
+ else
+ cookies = [Cookie.parse(response.headers['set-cookie'])];
- if (!response.headers['set-cookie']) {
- console.log(" -- no cookies to set");
- return;
- }
+ console.log(" -- received cookies: "+cookies)
- if (response.headers['set-cookie'] instanceof Array) {
- cookies = response.headers['set-cookie'].map(Cookie.parse);
- } else {
- cookies = [Cookie.parse(response.headers['set-cookie'])];
- }
+ var result = cookies.cookieString();
+ console.log(" -- using cookies: "+result)
+ return result;
+}
- for (var cookie of cookies) {
- console.log("Setting cookie: "+cookie.key+" = "+cookie.value)
- cordova.plugin.http.setCookie(
- grok_url,
- cookie,
- )
- }
+function make_post_body(params) {
+ var f = [];
+ for (var key in params) {
+ var encKey = encodeURIComponent(key);
+ var encValue = encodeURIComponent(params[key]);
+ f.push(encodedKey + '=' + encodedValue);
+ }
+ return f.join('&');
}
-export function grok_login1(callback) {
+///////////////////////////////////////
+
+export function grok_set_url(url) {
+ console.log("Requests will go to: "+url);
+ grok_url = url;
+}
+
+export async function grok_login1() {
+
+ var cookieString = await SecureStore.getItemAsync('cookies');
+
+ return new Promise((resolve, reject) => {
var result = {};
- cordova.plugin.http.get(grok_url,
- {},
- {},
- function(response) {
+ console.log("Sending cookies: "+cookieString);
- var html = $('<html>').append(
- $.parseHTML(response.data));
+ fetch(grok_url, {
+ method: 'POST',
+ body: make_post_body(
+ {
+ 'lj_form_auth': auth,
+ 'user': username,
+ 'password': password,
+ 'remember_me': 1,
+ 'login': 'Log+in',
+ }),
+ headers: {
+ 'Cookie': cookieString,
+ },
+ }).then((response) => {
- result['auth'] = html.find('[name="lj_form_auth"]').
- attr('value');
+ var html = $('<html>').append(
+ $.parseHTML(response.data));
- set_cookies(grok_url, response);
+ result['auth'] = html.find('[name="lj_form_auth"]').
+ attr('value');
- result['success'] = true;
+ result['cookies'] = cookie_string(response);
- callback(result);
- },
- function(response) {
- result['success'] = false;
- result['message'] = response.error;
+ resolve(result);
- callback(result);
- });
-}
+ }).catch((error) => {
+ reject(error);
+ });
+ });
+};
+
+export async function grok_login2(auth, username, password) {
-export function grok_login2(callback, auth, username, password) {
+ return new Promise((resolve, reject) => {
var result = {};
- cordova.plugin.http.post(grok_url,
- {
+ fetch(grok_url,
+ {
+ method: 'POST',
+ body: make_post_body(
+ {
'lj_form_auth': auth,
'user': username,
'password': password,
'remember_me': 1,
'login': 'Log+in',
+ }),
+ headers: {
+ 'Cookie': cookies,
},
- {},
- function(response) {
- console.log('----');
- console.log(response.headers);
- console.log('----');
- console.log(response.data);
-
- var html = $('<html>').append(
- $.parseHTML(response.data));
-
- var h1 = html.find('h1').html()
-
- if (h1.includes('Welcome back')) {
- result['success'] = true;
- } else {
- result['success'] = false;
-
- var blockquote = html.find('blockquote').html();
-
- if (blockquote.includes('wrong password')) {
- result['message'] = 'Wrong password.';
- } else if (blockquote.includes('This account name')) {
- result['message'] = 'Unknown username.';
- } else {
- result['message'] = 'Unknown error from site.';
- }
-
- console.log('Error from site:');
- console.log(blockquote);
- }
-
- callback(result);
- },
- function(response) {
- result['success'] = false;
- result['message'] = response.error;
- callback(result);
- });
+ },
+ ).then((response) => {
+
+ console.log('----');
+ console.log(response.headers);
+ console.log('----');
+ console.log(response.data);
+
+ var html = $('<html>').append(
+ $.parseHTML(response.data));
+
+ var h1 = html.find('h1').html()
+
+ if (h1.includes('Welcome back')) {
+ result['success'] = true;
+ } else {
+ result['success'] = false;
+
+ var blockquote = html.find('blockquote').html();
+
+ if (blockquote.includes('wrong password')) {
+ result['message'] = 'Wrong password.';
+ } else if (blockquote.includes('This account name')) {
+ result['message'] = 'Unknown username.';
+ } else {
+ result['message'] = 'Unknown error from site.';
+ }
+
+ console.log('Error from site:');
+ console.log(blockquote);
+ }
+
+ callback(result);
+
+ }).catch((error) => {
+ result['success'] = false;
+ result['message'] = error;
+
+ callback(result);
+ });
+ });
}
"dependencies": {
"@expo/vector-icons": "^12.0.0",
"@expo/webpack-config": "^0.16.11",
+ "@react-native-cookies/cookies": "^6.0.11",
"@react-navigation/bottom-tabs": "^6.0.5",
"@react-navigation/native": "^6.0.2",
"@react-navigation/native-stack": "^6.1.0",
"expo-constants": "~12.1.3",
"expo-font": "~10.0.3",
"expo-linking": "~2.4.2",
+ "expo-secure-store": "~11.0.3",
"expo-splash-screen": "~0.13.5",
"expo-status-bar": "~1.1.0",
"expo-web-browser": "~10.0.3",
+ "jquery": "^3.6.0",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-native": "0.64.3",
"react-native-safe-area-context": "3.3.2",
"react-native-screens": "~3.8.0",
- "react-native-web": "0.17.1"
+ "react-native-web": "0.17.1",
+ "tough-cookie": "^4.0.0"
},
"devDependencies": {
"@babel/core": "^7.12.9",