Server-class is functional
[gopher-lib.git] / common.js
1 /*jslint node: true */
2 /*jshint esversion: 6 */
3
4 'use strict';
5
6 const path = require('path');
7
8 const GopherURIPattern='^(gopher:\\/\\/)?(.+?(?=:|\\/|$))(:\\d+?(?=$|\\/))?(\\/(\\d|g|I|h|t|M)?)?([^#]+?(?=\\?|$|#))?(\\?.+?(?=$|#))?(#.+)?';
9
10 /** @class */
11 class GopherResource {
12
13         /**
14          * @param {string} host|url - Hostname or url, if url, do not provide other arguments
15          * @param {string} port - Port for the entry
16          * @param {string} selector - Selector for the entry
17          * @param {string} type - The type of entry (for example 'i')
18          * @param {string} name - The name to show to the user in a gopher-map
19          * @param {string} query - Search string to send to server (not expressed in gopher-map)
20          * @description Describes a gopher-resource (a menu-item)
21          */
22         constructor( host, port, selector, type, name, query ) {
23                 if(host && !port) {
24                         var regEx = new RegExp(GopherURIPattern);
25                         var matches = regEx.exec(decodeURI(host));
26                         try {
27                         this.host = matches[2];
28                         this.port = (matches[3])?matches[3].substring(1):'70';
29                         this.type = (matches[5])?matches[5]:'1';
30                         this.selector = (matches[6])?matches[6]:'';
31                         this.query = (matches[7])?matches[7].substring(1):false;
32                         this.name= (matches[8])?matches[8].substring(1):this.toURI();
33                         } catch(e) {
34                                 throw new Error('Not a valid gopher URI: '+host);
35                         }
36                 } else if(host && port && typeof selector === 'string' && type) {
37                         this.host=host;
38                         this.port=port;
39                         this.type=type;
40                         this.selector=selector;
41                         this.name=name;
42                         this.query=(query)?query:false;
43                 } else {
44                         throw new Error('Invalid arguments to constructor.');
45                 }
46                 if( !this.host || !this.port || !this.type || typeof this.selector !== 'string' ) {
47                         throw new Error('Not a valid GopherResource: '+JSON.stringify(this));
48                 }
49                 if(selector && selector.length>1) {
50                         this.selector = path.normalize(this.selector);
51                 }
52         }
53
54         toShortURI() {
55                 return encodeURI('gopher://'+this.host+':'+this.port+'/'+this.type+this.selector+( (this.query!==false)?'?'+this.query:'' ) );
56         }
57
58         toURI() {
59                 return this.toShortURI()+( (this.name)?'#'+encodeURIComponent(this.name):'' );
60
61         }
62
63         /**
64          * @method
65          * @description Return a goper-map formatted string representation of this resource
66          */
67         toDirectoryEntity() {
68                 return this.type+this.name+'\t'+this.selector+'\t'+this.host+'\t'+this.port+'\r\n';
69         }
70
71         toJson() {
72                 return JSON.stringify(this);
73         }
74 }
75
76 /**
77  * @method
78  * @memberof GopherResource
79  * @param {string} txt - Message for this info-item
80  * @description Create a new GopherResource with info text, suitable for menus
81  * @returns {GopherResource}
82  */
83 GopherResource.info = (txt)=>{
84         return new GopherResource('i', 1, '-', 'i', txt)
85 };
86
87 /**
88  * @method
89  * @memberof GopherResource
90  * @param {string} txt - Message for this error-item
91  * @description Create a new GopherResource with error text, suitable for menus
92  * @returns {GopherResource}
93  */
94 GopherResource.error = (txt)=>{
95         return new GopherResource('e', 1, '-', '3', txt)
96 };
97
98 const GopherType = {
99         info: 'i',
100         text: '0',
101         directory: '1',
102         phonebook: '2',
103         error: '3',
104         binhex: '4',
105         dosbinary: '5',
106         uuencoded: '6',
107         search: '7',
108         telnet: '8',
109         binary: '9',
110         redundant: '+',
111         tn3270: 'T',
112         gif: 'g',
113         image: 'I',
114         html: 'h',
115         mail: 'M'
116 };
117
118 module.exports = {
119     Resource: GopherResource,
120     Type: GopherType,
121     URIPattern: GopherURIPattern
122 }