├── .elpaignore ├── .github └── workflows │ └── test.yml ├── .gitignore ├── COPYING ├── Makefile ├── NOTES ├── README ├── doc ├── .gitignore ├── Makefile ├── doclicense.texi ├── gpl.texi └── web-server.texi ├── examples ├── 000-hello-world.el ├── 001-hello-world-utf8.el ├── 002-hello-world-html.el ├── 003-file-server.el ├── 004-url-param-echo.el ├── 005-post-echo.el ├── 006-basic-authentication.el ├── 007-org-mode-file-server.el ├── 008-file-upload.el ├── 009-web-socket.el ├── 010-current-buffer.el ├── 011-org-agenda.el ├── 012-search-bbdb.el ├── 013-org-export-service.el ├── 014-org-json.el ├── 015-auto-mode-server.el ├── 016-content-encoding-gzip.el ├── 017-transfer-encoding-chunked.el ├── 018-web-shell.el ├── 018-web-shell.html └── 018-web-shell.js ├── web-server-status-codes.el ├── web-server-test.el └── web-server.el /.elpaignore: -------------------------------------------------------------------------------- 1 | COPYING 2 | examples 3 | Makefile 4 | NOTES 5 | README 6 | stuff 7 | web-server-test.el 8 | 9 | ## Ignorable documentation files 10 | doc/dir 11 | doc/doclicense.texi 12 | doc/gpl.texi 13 | doc/Makefile 14 | doc/web-server.texi 15 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | emacs_version: 11 | - 24.3 12 | - 25.3 13 | - 26.3 14 | steps: 15 | - uses: purcell/setup-emacs@master 16 | with: 17 | version: ${{ matrix.emacs_version }} 18 | - uses: actions/checkout@v1 19 | - name: Run tests 20 | run: make src check 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.elc 2 | stuff 3 | benchmark 4 | web-server-* 5 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | EMACS := emacs 2 | BATCH=$(EMACS) --batch --execute '(add-to-list (quote load-path) "$(shell pwd)")' 3 | 4 | SRC=$(wildcard *.el) 5 | ELC=$(SRC:.el=.elc) 6 | 7 | .PHONY: src doc check clean 8 | all: src doc 9 | 10 | src: $(SRC) 11 | $(BATCH) -f batch-byte-compile $^ 12 | 13 | doc: 14 | $(MAKE) -C doc/ 15 | 16 | doc/web-server.info: 17 | $(MAKE) -C doc/ web-server.info 18 | 19 | doc/dir: 20 | $(MAKE) -C doc/ dir 21 | 22 | check: $(SRC) 23 | $(BATCH) -l cl -l ert -l web-server-test -f ert-run-tests-batch-and-exit 24 | 25 | clean: 26 | rm -rf $(ELC) $(PACKAGE) $(PACKAGE).tar 27 | $(MAKE) -C doc/ $(MAKECMDGOALS) 28 | 29 | # Packaging 30 | PARSE=grep "$(1):" web-server.el|sed 's/^.*$(1): //' 31 | NAME=web-server 32 | VERSION=$(shell $(call PARSE,Version)) 33 | DOC=$(shell head -1 web-server.el|sed 's/^.*--- //') 34 | REQ=$(shell $(call PARSE,Package-Requires)) 35 | DEFPKG=(define-package "$(NAME)" "$(VERSION)"\n "$(DOC)"\n (quote $(REQ))) 36 | PACKAGE=$(NAME)-$(VERSION) 37 | 38 | $(PACKAGE): $(filter-out web-server-test.el, $(SRC)) doc/web-server.info doc/dir 39 | mkdir -p $(PACKAGE) 40 | cp $^ $(PACKAGE) 41 | sed -n '/;;; Commentary:/,/;;; Code:/p' web-server.el|tail -n+3|head -n-2|cut -c4- >$(PACKAGE)/README 42 | echo -e '$(DEFPKG)' > $(PACKAGE)/$(NAME)-pkg.el 43 | 44 | $(PACKAGE).tar: $(PACKAGE) 45 | tar cf $@ $< 46 | 47 | package: $(PACKAGE).tar 48 | -------------------------------------------------------------------------------- /NOTES: -------------------------------------------------------------------------------- 1 | -*- org -*- 2 | #+Title: Notes and Tasks 3 | #+HTML_HEAD: 4 | #+Options: ^:{} 5 | 6 | * Notes 7 | * Tasks [19/22] 8 | ** DONE pass all tests on Windows [2/2] 9 | Currently two failing tests. 10 | 11 | - [X] ws/simple-post returns "you said nil" instead of "you said foo" 12 | 13 | - [X] ws/in-directory-p is failing because it assumes "/tmp" which 14 | doesn't work on windows 15 | 16 | ** DONE Content and Transfer encodings 17 | - Content and Transfer encoding values 18 | http://www.iana.org/assignments/http-parameters/http-parameters.xhtml 19 | - http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6 20 | - http://en.wikipedia.org/wiki/Chunked_transfer_encoding 21 | - http://tools.ietf.org/html/rfc1945#section-7.2 22 | - http://tools.ietf.org/rfc/rfc1945.txt 23 | 24 | Some issue as to whether compression is better done as a "Content 25 | Encoding" which actually changes the content, or as a "Transfer 26 | Encoding", which doesn't change the content, just the messages. 27 | 28 | The latter seems preferable, but possibly less widely supported. See 29 | http://stackoverflow.com/questions/11641923/transfer-encoding-gzip-vs-content-encoding-gzip. 30 | 31 | - content-coding 32 | - compress :: Unix =compress= program (rfc2616) 33 | - deflate :: =zlib= (see http://www.iana.org/go/rfc1950) format with 34 | =defalte= compression (rfc2616) 35 | - exi :: W3c efficient XML (see http://www.w3.org/TR/exi/) 36 | - gzip :: GNU zip (rfc2616) 37 | - identity :: does nothing 38 | - pack200-zip :: specific to Java archives (see 39 | http://www.jcp.org/en/jsr/detail?id=200) 40 | - transfer-coding 41 | - chunked :: (rfc2616) 42 | - compress :: same as above 43 | - deflate :: same as above 44 | - gzip :: same as above 45 | - tail-header 46 | - Content-MD5 :: Base64 encoded binary MD5 sum of content 47 | 48 | Maybe we can set the coding system of the process with 49 | =define-coding-system=, specifically using the =:pre-write-conversion= 50 | flag to e.g., gzip or chunkify the contents. 51 | 52 | ** DONE web sockets 53 | - http://en.wikipedia.org/wiki/WebSocket 54 | - http://tools.ietf.org/html/rfc6455 55 | 56 | ** more examples [4/4] 57 | *** DONE Org-mode agenda 58 | Already exists as part of org-ehtml. 59 | file:examples/011-org-agenda.el 60 | 61 | *** DONE display the current buffer 62 | Idea stolen from elnode. 63 | file:examples/010-current-buffer.el 64 | 65 | *** DONE browse the BBDB 66 | file:examples/012-search-bbdb.el 67 | *** DONE org-mode export server 68 | 1. upload a file 69 | 2. supply an export type 70 | 3. return the exported version of the file 71 | 72 | ** DONE handle large files 73 | When large files arrive quickly, the filter functions are called while 74 | they are still running on the previous chunk, this leads to nasty race 75 | conditions for the state of the request object. 76 | 77 | Either introduce some check to wait on new input if input is currently 78 | being parsed, or wait until all input has arrived before doing any 79 | parsing. 80 | 81 | Now using an =active= field on request objects to avoid race 82 | conditions when new header text is received while the parsing function 83 | is still active. 84 | 85 | ** TODO robustness to bad requests [0/2] 86 | Low priority, just [[*running%20behind%20a%20proxy][run behind a proxy]]. 87 | 88 | *** TODO request timeout 89 | *** TODO maximum request size 90 | ** DONE authentication [2/2] 91 | - State "HOLD" from "TODO" [2014-02-10 Mon 19:06] \\ 92 | digest may not be worth it, just run Basic over HTTPS 93 | *** DONE Basic 94 | http://en.wikipedia.org/wiki/Basic_access_authentication 95 | 96 | *** CANCELED Digest 97 | http://en.wikipedia.org/wiki/Digest_access_authentication 98 | 99 | If this is implemented, it would be good to implement some safeguards 100 | against common attacks. 101 | 102 | #+begin_quote 103 | - Server nonce is allowed to contain timestamps. Therefore the server 104 | may inspect nonce attributes submitted by clients, to prevent replay 105 | attacks. 106 | - Server is also allowed to maintain a list of recently issued or used 107 | server nonce values to prevent reuse. 108 | #+end_quote 109 | 110 | ** incremental handler calls 111 | not sure if the extra performance is worth the added complexity 112 | 113 | Before the header is fully parsed, call any potential handlers. 114 | Include a field in the request object to indicate that the request 115 | isn't finished being received so handlers can return and wait to be 116 | called again. 117 | 118 | Also, put a catch in the filter function and allow the =headers= 119 | function on the request object to throw to said catch aborting the 120 | handler and waiting for the rest of the input. 121 | 122 | ** DONE Documentation [6/6] 123 | - [X] introduction 124 | - [X] handlers 125 | - [X] request headers 126 | - [X] usage examples 127 | - [X] list of functions 128 | 129 | Notes to touch upon 130 | - [X] how to set content type 131 | 132 | ** DONE Handle POST requests 133 | 1. read standard for POST data 134 | 2. parse multi-line headers with boundaries 135 | 136 | For now keep this all incremental and in ws-filter. 137 | 138 | ** DONE Makefile 139 | - byte-compile 140 | - package 141 | - test 142 | - benchmark 143 | ** DONE catch errors and return an error code 144 | include an easy error handler like the 404 handler 145 | 146 | ** DONE better parsing of multipart form blocks 147 | parse more than just the content-type headers. 148 | 149 | ** DONE non-multipart form data 150 | e.g., parameter strings 151 | 152 | ** DONE some more convenience functionality [6/6] 153 | - [X] strip and parse URL query string 154 | - [X] parse urlencoded post data 155 | - [X] think about defaulting to (name . content) for form elements 156 | - [X] maybe don't require a non-nil return to cancel the connection, 157 | instead only keep open if =:keep-alive= is returned 158 | - [X] function to send a file (with mime handling) 159 | - [X] send a 404 with some default text 160 | 161 | ** CANCELED Lazy header processing 162 | - State "CANCELED" from "TODO" [2013-12-25 Wed 12:21] \\ 163 | premature optimization 164 | Use lazy sequence functions for header a-list to avoid parsing all 165 | headers. For regexp matchers should stop when matched header is 166 | encountered (often the first one when :GET), For function matchers 167 | provide lazy version of assoc. 168 | 169 | Also, there is the issue of how a lazy request for more parameters 170 | should act before all incoming text has been received. Emacs does not 171 | provide a light-weight mechanism for a function to wait for incoming 172 | process text without something gross like the =(sit-for 0.1)= used in 173 | the test suite. 174 | 175 | ** use gnutls for https 176 | low priority -- just [[*running%20behind%20an%20https%20proxy][run behind an https proxy]]. 177 | 178 | This will be a pain, and will require expanding [[info:emacs-gnutls]] to 179 | add support for starting server processes, currently only client 180 | processes are supported. 181 | ** screen cast? 182 | - http://en.wikipedia.org/wiki/XVidCap 183 | - https://aur.archlinux.org/packages/xvidcap/ 184 | 185 | * Tutorials 186 | The following tutorials walk through common usage scenarios including 187 | installing the Emacs web-server and running it behind a proxy. 188 | Install the Emacs web-server and run =(info "web-server")= to browse 189 | the full manual within Emacs, or view the HTML version at 190 | [[http://eschulte.github.io/emacs-web-server/][emacs-web-server]]. 191 | 192 | ** Installation and running a server 193 | Most easily installable through the GNU ELPA, run =M-x 194 | package-list-packages= select =web-server= and install. Alternately, 195 | install from the git repository at 196 | https://github.com/eschulte/emacs-web-server and update your the load. 197 | 198 | 1. Ensure that you have Emacs version 24 or greater installed. 199 | 200 | #+begin_src sh :results scalar 201 | emacs --version 202 | #+end_src 203 | 204 | : GNU Emacs 24.3.1 205 | : Copyright (C) 2013 Free Software Foundation, Inc. 206 | : GNU Emacs comes with ABSOLUTELY NO WARRANTY. 207 | : You may redistribute copies of Emacs 208 | : under the terms of the GNU General Public License. 209 | : For more information about these matters, see the file named COPYING. 210 | 211 | 2. Download and unpack the zip archive of the Emacs web-server code 212 | from [[https://github.com/eschulte/emacs-web-server/archive/master.zip][emacs-web-server-master.zip]] or clone the source code 213 | repository with [[http://git-scm.com/][git]]. 214 | 215 | #+begin_src sh 216 | git clone https://github.com/eschulte/emacs-web-server.git 217 | #+end_src 218 | 219 | 3. Move into the root of the =emacs-web-server/= directory and 220 | optionally run =make= to compile the web-server code, and run =make 221 | check= to test your web-server install. 222 | 223 | #+begin_src sh 224 | make 225 | make check 226 | #+end_src 227 | 228 | 4. From the root of the =emacs-web-server/= directory, start an 229 | instance of Emacs with web-server loaded. 230 | 231 | #+begin_src sh 232 | emacs -Q -L . -l web-server 233 | #+end_src 234 | 235 | Alternately, from an already running Emacs instance, add this 236 | directory to the load path and load the web server with the 237 | following. 238 | 239 | #+begin_src emacs-lisp 240 | (add-to-list 'load-path "path/to/emacs-web-server") 241 | (require 'web-server) 242 | #+end_src 243 | 244 | 5. Evaluate the following code in =*scratch*= buffer of this Emacs 245 | instance. 246 | 247 | #+begin_src emacs-lisp 248 | (ws-start 249 | (lambda (request) 250 | (with-slots (process headers) request 251 | (ws-response-header process 200 '("Content-type" . "text/plain")) 252 | (process-send-string process "hello world"))) 253 | 9000) 254 | #+end_src 255 | 256 | 6. Browse to http://localhost:9000 to see that the web-server is 257 | running. 258 | 259 | 7. Read the web-server [[http://eschulte.github.io/emacs-web-server/index.html#Top][manual]] and work through other [[http://eschulte.github.io/emacs-web-server/Usage-Examples.html#Usage-Examples][Usage Examples]]. 260 | 261 | ** Running behind a proxy 262 | Public-facing instance of the Emacs web-server should be run behind a 263 | more established web server such as [[http://httpd.apache.org/][Apache]] or [[http://wiki.nginx.org][Nginx]] to provide 264 | additional robustness and security. 265 | 266 | The following example Apache configuration may be used to have a 267 | public facing Apache server listening on port 80 proxy requests to a 268 | local web-server instance running on port 8888 of the same machine. 269 | 270 | #+begin_src conf 271 | 272 | ServerName yourserver.com 273 | 274 | ProxyPass / http://localhost:8888/ 275 | 276 | #+end_src 277 | 278 | A similar Nginx configuration is available at 279 | http://wiki.nginx.org/LoadBalanceExample. 280 | 281 | ** Running behind an https proxy 282 | The following example configurations will cause Apache or Nginx to act 283 | as an HTTPS proxy for an instance of the Emacs web server running on 284 | the same machine. With this setup Apache speaks HTTPS to the outside 285 | world, and communicates with the Emacs web server using HTTP. This 286 | allows use of HTTPS even though the Emacs web server does not 287 | implement HTTPS itself. This setup is recommended for any setup, but 288 | should be considered *required* for sites using BASIC HTTP 289 | Authentication. 290 | 291 | *** Apache 292 | This requires that Apache has =mod_proxy= and =mod_ssl= enabled, and 293 | that the certificate and key files required for SSL are present. This 294 | these requirements satisfied, and assuming the Emacs web server is 295 | listening on port 8888 and is running on the same machine as the 296 | Apache web server an Apache virtual host configuration such as the 297 | following. 298 | 299 | #+begin_src conf 300 | 301 | ProxyPreserveHost On 302 | ServerName yourserver.com 303 | 304 | SSLEngine On 305 | SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem 306 | SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key 307 | 308 | ProxyPass / http://localhost:8888/ 309 | ProxyPassReverse / http://localhost:8888/ 310 | 311 | #+end_src 312 | 313 | *** Nginx 314 | See the following for instructions configuring Nginx as an HTTPS 315 | proxy. 316 | - http://wiki.nginx.org/SSL-Offloader#sslproxy.conf 317 | - http://www.cyberciti.biz/faq/howto-linux-unix-setup-nginx-ssl-proxy/ 318 | 319 | ** COMMENT documentation for running in a chroot jail 320 | See https://wiki.archlinux.org/index.php/nginx#Installation_in_a_chroot. 321 | 322 | * Bugs [1/1] 323 | ** DONE Sometimes servers don't stop cleanly 324 | - specifically servers with active client process 325 | - maybe also implement a =ws-stop-all= function 326 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Emacs Web Server 2 | 3 | DESCRIPTION 4 | A web server in Emacs running handlers written in Emacs Lisp. 5 | 6 | REQUIREMENTS 7 | Emacs 24.3 or later. 8 | 9 | STATUS 10 | Supports HTTP GET and POST requests including URL-encoded 11 | parameters, multipart/form data and file uploads. Supports web 12 | sockets. Reasonably performant, faster than Elnode [1]. This is 13 | a new project without much extended use so there are likely bugs 14 | and potentially security issues. That said it consists of little 15 | more than HTTP header parsing logic perched atop Emacs' existing 16 | network process primitives, so it should be fairly robust. 17 | 18 | [1] http://eschulte.github.io/emacs-web-server/benchmark/ 19 | 20 | USAGE 21 | See the examples/ directory in this repository for examples 22 | demonstrating usage. The Emacs web-server is also used to run a 23 | paste server [2], serve editable Org-mode pages [3] and serve 24 | files for Cask [4]. 25 | 26 | [2] https://github.com/eschulte/el-sprunge 27 | [3] https://github.com/eschulte/org-ehtml 28 | [4] https://github.com/cask/cask 29 | 30 | Available from the GNU ELPA [5]. The tutorials page [6] walks 31 | through usage scenarios including installing the Emacs web-server 32 | and running it behind a proxy. 33 | 34 | [5] http://elpa.gnu.org/ 35 | [6] http://eschulte.github.io/emacs-web-server/tutorials/ 36 | 37 | Run `make check' to run the included test suite. 38 | 39 | DOCUMENTATION 40 | Run `make doc' to build the texinfo documentation, also available 41 | online [6]. 42 | 43 | [6] http://eschulte.github.io/emacs-web-server 44 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | dir 2 | web-server/ 3 | *.info 4 | *.html 5 | *.svg 6 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | all: web-server web-server.info dir 2 | 3 | web-server: web-server.texi 4 | makeinfo --html $< 5 | 6 | web-server.info: web-server.texi 7 | makeinfo $< 8 | 9 | dir: web-server.info 10 | install-info --info-dir=./ $< 11 | 12 | clean: 13 | rm -f *.info; 14 | rm -rf web-server/ 15 | -------------------------------------------------------------------------------- /doc/doclicense.texi: -------------------------------------------------------------------------------- 1 | @c -*-texinfo-*- 2 | @c The GNU Free Documentation License. 3 | @center Version 1.3, 3 November 2008 4 | 5 | @c This file is intended to be included within another document, 6 | @c hence no sectioning command or @node. 7 | 8 | @display 9 | Copyright @copyright{} 2000, 2001, 2002, 2007, 2008, 2009 Free Software Foundation, Inc. 10 | @uref{http://fsf.org/} 11 | 12 | Everyone is permitted to copy and distribute verbatim copies 13 | of this license document, but changing it is not allowed. 14 | @end display 15 | 16 | @enumerate 0 17 | @item 18 | PREAMBLE 19 | 20 | The purpose of this License is to make a manual, textbook, or other 21 | functional and useful document @dfn{free} in the sense of freedom: to 22 | assure everyone the effective freedom to copy and redistribute it, 23 | with or without modifying it, either commercially or noncommercially. 24 | Secondarily, this License preserves for the author and publisher a way 25 | to get credit for their work, while not being considered responsible 26 | for modifications made by others. 27 | 28 | This License is a kind of ``copyleft'', which means that derivative 29 | works of the document must themselves be free in the same sense. It 30 | complements the GNU General Public License, which is a copyleft 31 | license designed for free software. 32 | 33 | We have designed this License in order to use it for manuals for free 34 | software, because free software needs free documentation: a free 35 | program should come with manuals providing the same freedoms that the 36 | software does. But this License is not limited to software manuals; 37 | it can be used for any textual work, regardless of subject matter or 38 | whether it is published as a printed book. We recommend this License 39 | principally for works whose purpose is instruction or reference. 40 | 41 | @item 42 | APPLICABILITY AND DEFINITIONS 43 | 44 | This License applies to any manual or other work, in any medium, that 45 | contains a notice placed by the copyright holder saying it can be 46 | distributed under the terms of this License. Such a notice grants a 47 | world-wide, royalty-free license, unlimited in duration, to use that 48 | work under the conditions stated herein. The ``Document'', below, 49 | refers to any such manual or work. Any member of the public is a 50 | licensee, and is addressed as ``you''. You accept the license if you 51 | copy, modify or distribute the work in a way requiring permission 52 | under copyright law. 53 | 54 | A ``Modified Version'' of the Document means any work containing the 55 | Document or a portion of it, either copied verbatim, or with 56 | modifications and/or translated into another language. 57 | 58 | A ``Secondary Section'' is a named appendix or a front-matter section 59 | of the Document that deals exclusively with the relationship of the 60 | publishers or authors of the Document to the Document's overall 61 | subject (or to related matters) and contains nothing that could fall 62 | directly within that overall subject. (Thus, if the Document is in 63 | part a textbook of mathematics, a Secondary Section may not explain 64 | any mathematics.) The relationship could be a matter of historical 65 | connection with the subject or with related matters, or of legal, 66 | commercial, philosophical, ethical or political position regarding 67 | them. 68 | 69 | The ``Invariant Sections'' are certain Secondary Sections whose titles 70 | are designated, as being those of Invariant Sections, in the notice 71 | that says that the Document is released under this License. If a 72 | section does not fit the above definition of Secondary then it is not 73 | allowed to be designated as Invariant. The Document may contain zero 74 | Invariant Sections. If the Document does not identify any Invariant 75 | Sections then there are none. 76 | 77 | The ``Cover Texts'' are certain short passages of text that are listed, 78 | as Front-Cover Texts or Back-Cover Texts, in the notice that says that 79 | the Document is released under this License. A Front-Cover Text may 80 | be at most 5 words, and a Back-Cover Text may be at most 25 words. 81 | 82 | A ``Transparent'' copy of the Document means a machine-readable copy, 83 | represented in a format whose specification is available to the 84 | general public, that is suitable for revising the document 85 | straightforwardly with generic text editors or (for images composed of 86 | pixels) generic paint programs or (for drawings) some widely available 87 | drawing editor, and that is suitable for input to text formatters or 88 | for automatic translation to a variety of formats suitable for input 89 | to text formatters. A copy made in an otherwise Transparent file 90 | format whose markup, or absence of markup, has been arranged to thwart 91 | or discourage subsequent modification by readers is not Transparent. 92 | An image format is not Transparent if used for any substantial amount 93 | of text. A copy that is not ``Transparent'' is called ``Opaque''. 94 | 95 | Examples of suitable formats for Transparent copies include plain 96 | @sc{ascii} without markup, Texinfo input format, La@TeX{} input 97 | format, @acronym{SGML} or @acronym{XML} using a publicly available 98 | @acronym{DTD}, and standard-conforming simple @acronym{HTML}, 99 | PostScript or @acronym{PDF} designed for human modification. Examples 100 | of transparent image formats include @acronym{PNG}, @acronym{XCF} and 101 | @acronym{JPG}. Opaque formats include proprietary formats that can be 102 | read and edited only by proprietary word processors, @acronym{SGML} or 103 | @acronym{XML} for which the @acronym{DTD} and/or processing tools are 104 | not generally available, and the machine-generated @acronym{HTML}, 105 | PostScript or @acronym{PDF} produced by some word processors for 106 | output purposes only. 107 | 108 | The ``Title Page'' means, for a printed book, the title page itself, 109 | plus such following pages as are needed to hold, legibly, the material 110 | this License requires to appear in the title page. For works in 111 | formats which do not have any title page as such, ``Title Page'' means 112 | the text near the most prominent appearance of the work's title, 113 | preceding the beginning of the body of the text. 114 | 115 | The ``publisher'' means any person or entity that distributes copies 116 | of the Document to the public. 117 | 118 | A section ``Entitled XYZ'' means a named subunit of the Document whose 119 | title either is precisely XYZ or contains XYZ in parentheses following 120 | text that translates XYZ in another language. (Here XYZ stands for a 121 | specific section name mentioned below, such as ``Acknowledgements'', 122 | ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' 123 | of such a section when you modify the Document means that it remains a 124 | section ``Entitled XYZ'' according to this definition. 125 | 126 | The Document may include Warranty Disclaimers next to the notice which 127 | states that this License applies to the Document. These Warranty 128 | Disclaimers are considered to be included by reference in this 129 | License, but only as regards disclaiming warranties: any other 130 | implication that these Warranty Disclaimers may have is void and has 131 | no effect on the meaning of this License. 132 | 133 | @item 134 | VERBATIM COPYING 135 | 136 | You may copy and distribute the Document in any medium, either 137 | commercially or noncommercially, provided that this License, the 138 | copyright notices, and the license notice saying this License applies 139 | to the Document are reproduced in all copies, and that you add no other 140 | conditions whatsoever to those of this License. You may not use 141 | technical measures to obstruct or control the reading or further 142 | copying of the copies you make or distribute. However, you may accept 143 | compensation in exchange for copies. If you distribute a large enough 144 | number of copies you must also follow the conditions in section 3. 145 | 146 | You may also lend copies, under the same conditions stated above, and 147 | you may publicly display copies. 148 | 149 | @item 150 | COPYING IN QUANTITY 151 | 152 | If you publish printed copies (or copies in media that commonly have 153 | printed covers) of the Document, numbering more than 100, and the 154 | Document's license notice requires Cover Texts, you must enclose the 155 | copies in covers that carry, clearly and legibly, all these Cover 156 | Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on 157 | the back cover. Both covers must also clearly and legibly identify 158 | you as the publisher of these copies. The front cover must present 159 | the full title with all words of the title equally prominent and 160 | visible. You may add other material on the covers in addition. 161 | Copying with changes limited to the covers, as long as they preserve 162 | the title of the Document and satisfy these conditions, can be treated 163 | as verbatim copying in other respects. 164 | 165 | If the required texts for either cover are too voluminous to fit 166 | legibly, you should put the first ones listed (as many as fit 167 | reasonably) on the actual cover, and continue the rest onto adjacent 168 | pages. 169 | 170 | If you publish or distribute Opaque copies of the Document numbering 171 | more than 100, you must either include a machine-readable Transparent 172 | copy along with each Opaque copy, or state in or with each Opaque copy 173 | a computer-network location from which the general network-using 174 | public has access to download using public-standard network protocols 175 | a complete Transparent copy of the Document, free of added material. 176 | If you use the latter option, you must take reasonably prudent steps, 177 | when you begin distribution of Opaque copies in quantity, to ensure 178 | that this Transparent copy will remain thus accessible at the stated 179 | location until at least one year after the last time you distribute an 180 | Opaque copy (directly or through your agents or retailers) of that 181 | edition to the public. 182 | 183 | It is requested, but not required, that you contact the authors of the 184 | Document well before redistributing any large number of copies, to give 185 | them a chance to provide you with an updated version of the Document. 186 | 187 | @item 188 | MODIFICATIONS 189 | 190 | You may copy and distribute a Modified Version of the Document under 191 | the conditions of sections 2 and 3 above, provided that you release 192 | the Modified Version under precisely this License, with the Modified 193 | Version filling the role of the Document, thus licensing distribution 194 | and modification of the Modified Version to whoever possesses a copy 195 | of it. In addition, you must do these things in the Modified Version: 196 | 197 | @enumerate A 198 | @item 199 | Use in the Title Page (and on the covers, if any) a title distinct 200 | from that of the Document, and from those of previous versions 201 | (which should, if there were any, be listed in the History section 202 | of the Document). You may use the same title as a previous version 203 | if the original publisher of that version gives permission. 204 | 205 | @item 206 | List on the Title Page, as authors, one or more persons or entities 207 | responsible for authorship of the modifications in the Modified 208 | Version, together with at least five of the principal authors of the 209 | Document (all of its principal authors, if it has fewer than five), 210 | unless they release you from this requirement. 211 | 212 | @item 213 | State on the Title page the name of the publisher of the 214 | Modified Version, as the publisher. 215 | 216 | @item 217 | Preserve all the copyright notices of the Document. 218 | 219 | @item 220 | Add an appropriate copyright notice for your modifications 221 | adjacent to the other copyright notices. 222 | 223 | @item 224 | Include, immediately after the copyright notices, a license notice 225 | giving the public permission to use the Modified Version under the 226 | terms of this License, in the form shown in the Addendum below. 227 | 228 | @item 229 | Preserve in that license notice the full lists of Invariant Sections 230 | and required Cover Texts given in the Document's license notice. 231 | 232 | @item 233 | Include an unaltered copy of this License. 234 | 235 | @item 236 | Preserve the section Entitled ``History'', Preserve its Title, and add 237 | to it an item stating at least the title, year, new authors, and 238 | publisher of the Modified Version as given on the Title Page. If 239 | there is no section Entitled ``History'' in the Document, create one 240 | stating the title, year, authors, and publisher of the Document as 241 | given on its Title Page, then add an item describing the Modified 242 | Version as stated in the previous sentence. 243 | 244 | @item 245 | Preserve the network location, if any, given in the Document for 246 | public access to a Transparent copy of the Document, and likewise 247 | the network locations given in the Document for previous versions 248 | it was based on. These may be placed in the ``History'' section. 249 | You may omit a network location for a work that was published at 250 | least four years before the Document itself, or if the original 251 | publisher of the version it refers to gives permission. 252 | 253 | @item 254 | For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve 255 | the Title of the section, and preserve in the section all the 256 | substance and tone of each of the contributor acknowledgements and/or 257 | dedications given therein. 258 | 259 | @item 260 | Preserve all the Invariant Sections of the Document, 261 | unaltered in their text and in their titles. Section numbers 262 | or the equivalent are not considered part of the section titles. 263 | 264 | @item 265 | Delete any section Entitled ``Endorsements''. Such a section 266 | may not be included in the Modified Version. 267 | 268 | @item 269 | Do not retitle any existing section to be Entitled ``Endorsements'' or 270 | to conflict in title with any Invariant Section. 271 | 272 | @item 273 | Preserve any Warranty Disclaimers. 274 | @end enumerate 275 | 276 | If the Modified Version includes new front-matter sections or 277 | appendices that qualify as Secondary Sections and contain no material 278 | copied from the Document, you may at your option designate some or all 279 | of these sections as invariant. To do this, add their titles to the 280 | list of Invariant Sections in the Modified Version's license notice. 281 | These titles must be distinct from any other section titles. 282 | 283 | You may add a section Entitled ``Endorsements'', provided it contains 284 | nothing but endorsements of your Modified Version by various 285 | parties---for example, statements of peer review or that the text has 286 | been approved by an organization as the authoritative definition of a 287 | standard. 288 | 289 | You may add a passage of up to five words as a Front-Cover Text, and a 290 | passage of up to 25 words as a Back-Cover Text, to the end of the list 291 | of Cover Texts in the Modified Version. Only one passage of 292 | Front-Cover Text and one of Back-Cover Text may be added by (or 293 | through arrangements made by) any one entity. If the Document already 294 | includes a cover text for the same cover, previously added by you or 295 | by arrangement made by the same entity you are acting on behalf of, 296 | you may not add another; but you may replace the old one, on explicit 297 | permission from the previous publisher that added the old one. 298 | 299 | The author(s) and publisher(s) of the Document do not by this License 300 | give permission to use their names for publicity for or to assert or 301 | imply endorsement of any Modified Version. 302 | 303 | @item 304 | COMBINING DOCUMENTS 305 | 306 | You may combine the Document with other documents released under this 307 | License, under the terms defined in section 4 above for modified 308 | versions, provided that you include in the combination all of the 309 | Invariant Sections of all of the original documents, unmodified, and 310 | list them all as Invariant Sections of your combined work in its 311 | license notice, and that you preserve all their Warranty Disclaimers. 312 | 313 | The combined work need only contain one copy of this License, and 314 | multiple identical Invariant Sections may be replaced with a single 315 | copy. If there are multiple Invariant Sections with the same name but 316 | different contents, make the title of each such section unique by 317 | adding at the end of it, in parentheses, the name of the original 318 | author or publisher of that section if known, or else a unique number. 319 | Make the same adjustment to the section titles in the list of 320 | Invariant Sections in the license notice of the combined work. 321 | 322 | In the combination, you must combine any sections Entitled ``History'' 323 | in the various original documents, forming one section Entitled 324 | ``History''; likewise combine any sections Entitled ``Acknowledgements'', 325 | and any sections Entitled ``Dedications''. You must delete all 326 | sections Entitled ``Endorsements.'' 327 | 328 | @item 329 | COLLECTIONS OF DOCUMENTS 330 | 331 | You may make a collection consisting of the Document and other documents 332 | released under this License, and replace the individual copies of this 333 | License in the various documents with a single copy that is included in 334 | the collection, provided that you follow the rules of this License for 335 | verbatim copying of each of the documents in all other respects. 336 | 337 | You may extract a single document from such a collection, and distribute 338 | it individually under this License, provided you insert a copy of this 339 | License into the extracted document, and follow this License in all 340 | other respects regarding verbatim copying of that document. 341 | 342 | @item 343 | AGGREGATION WITH INDEPENDENT WORKS 344 | 345 | A compilation of the Document or its derivatives with other separate 346 | and independent documents or works, in or on a volume of a storage or 347 | distribution medium, is called an ``aggregate'' if the copyright 348 | resulting from the compilation is not used to limit the legal rights 349 | of the compilation's users beyond what the individual works permit. 350 | When the Document is included in an aggregate, this License does not 351 | apply to the other works in the aggregate which are not themselves 352 | derivative works of the Document. 353 | 354 | If the Cover Text requirement of section 3 is applicable to these 355 | copies of the Document, then if the Document is less than one half of 356 | the entire aggregate, the Document's Cover Texts may be placed on 357 | covers that bracket the Document within the aggregate, or the 358 | electronic equivalent of covers if the Document is in electronic form. 359 | Otherwise they must appear on printed covers that bracket the whole 360 | aggregate. 361 | 362 | @item 363 | TRANSLATION 364 | 365 | Translation is considered a kind of modification, so you may 366 | distribute translations of the Document under the terms of section 4. 367 | Replacing Invariant Sections with translations requires special 368 | permission from their copyright holders, but you may include 369 | translations of some or all Invariant Sections in addition to the 370 | original versions of these Invariant Sections. You may include a 371 | translation of this License, and all the license notices in the 372 | Document, and any Warranty Disclaimers, provided that you also include 373 | the original English version of this License and the original versions 374 | of those notices and disclaimers. In case of a disagreement between 375 | the translation and the original version of this License or a notice 376 | or disclaimer, the original version will prevail. 377 | 378 | If a section in the Document is Entitled ``Acknowledgements'', 379 | ``Dedications'', or ``History'', the requirement (section 4) to Preserve 380 | its Title (section 1) will typically require changing the actual 381 | title. 382 | 383 | @item 384 | TERMINATION 385 | 386 | You may not copy, modify, sublicense, or distribute the Document 387 | except as expressly provided under this License. Any attempt 388 | otherwise to copy, modify, sublicense, or distribute it is void, and 389 | will automatically terminate your rights under this License. 390 | 391 | However, if you cease all violation of this License, then your license 392 | from a particular copyright holder is reinstated (a) provisionally, 393 | unless and until the copyright holder explicitly and finally 394 | terminates your license, and (b) permanently, if the copyright holder 395 | fails to notify you of the violation by some reasonable means prior to 396 | 60 days after the cessation. 397 | 398 | Moreover, your license from a particular copyright holder is 399 | reinstated permanently if the copyright holder notifies you of the 400 | violation by some reasonable means, this is the first time you have 401 | received notice of violation of this License (for any work) from that 402 | copyright holder, and you cure the violation prior to 30 days after 403 | your receipt of the notice. 404 | 405 | Termination of your rights under this section does not terminate the 406 | licenses of parties who have received copies or rights from you under 407 | this License. If your rights have been terminated and not permanently 408 | reinstated, receipt of a copy of some or all of the same material does 409 | not give you any rights to use it. 410 | 411 | @item 412 | FUTURE REVISIONS OF THIS LICENSE 413 | 414 | The Free Software Foundation may publish new, revised versions 415 | of the GNU Free Documentation License from time to time. Such new 416 | versions will be similar in spirit to the present version, but may 417 | differ in detail to address new problems or concerns. See 418 | @uref{http://www.gnu.org/copyleft/}. 419 | 420 | Each version of the License is given a distinguishing version number. 421 | If the Document specifies that a particular numbered version of this 422 | License ``or any later version'' applies to it, you have the option of 423 | following the terms and conditions either of that specified version or 424 | of any later version that has been published (not as a draft) by the 425 | Free Software Foundation. If the Document does not specify a version 426 | number of this License, you may choose any version ever published (not 427 | as a draft) by the Free Software Foundation. If the Document 428 | specifies that a proxy can decide which future versions of this 429 | License can be used, that proxy's public statement of acceptance of a 430 | version permanently authorizes you to choose that version for the 431 | Document. 432 | 433 | @item 434 | RELICENSING 435 | 436 | ``Massive Multiauthor Collaboration Site'' (or ``MMC Site'') means any 437 | World Wide Web server that publishes copyrightable works and also 438 | provides prominent facilities for anybody to edit those works. A 439 | public wiki that anybody can edit is an example of such a server. A 440 | ``Massive Multiauthor Collaboration'' (or ``MMC'') contained in the 441 | site means any set of copyrightable works thus published on the MMC 442 | site. 443 | 444 | ``CC-BY-SA'' means the Creative Commons Attribution-Share Alike 3.0 445 | license published by Creative Commons Corporation, a not-for-profit 446 | corporation with a principal place of business in San Francisco, 447 | California, as well as future copyleft versions of that license 448 | published by that same organization. 449 | 450 | ``Incorporate'' means to publish or republish a Document, in whole or 451 | in part, as part of another Document. 452 | 453 | An MMC is ``eligible for relicensing'' if it is licensed under this 454 | License, and if all works that were first published under this License 455 | somewhere other than this MMC, and subsequently incorporated in whole 456 | or in part into the MMC, (1) had no cover texts or invariant sections, 457 | and (2) were thus incorporated prior to November 1, 2008. 458 | 459 | The operator of an MMC Site may republish an MMC contained in the site 460 | under CC-BY-SA on the same site at any time before August 1, 2009, 461 | provided the MMC is eligible for relicensing. 462 | 463 | @end enumerate 464 | 465 | @page 466 | @heading ADDENDUM: How to use this License for your documents 467 | 468 | To use this License in a document you have written, include a copy of 469 | the License in the document and put the following copyright and 470 | license notices just after the title page: 471 | 472 | @smallexample 473 | @group 474 | Copyright (C) @var{year} @var{your name}. 475 | Permission is granted to copy, distribute and/or modify this document 476 | under the terms of the GNU Free Documentation License, Version 1.3 477 | or any later version published by the Free Software Foundation; 478 | with no Invariant Sections, no Front-Cover Texts, and no Back-Cover 479 | Texts. A copy of the license is included in the section entitled ``GNU 480 | Free Documentation License''. 481 | @end group 482 | @end smallexample 483 | 484 | If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, 485 | replace the ``with@dots{}Texts.'' line with this: 486 | 487 | @smallexample 488 | @group 489 | with the Invariant Sections being @var{list their titles}, with 490 | the Front-Cover Texts being @var{list}, and with the Back-Cover Texts 491 | being @var{list}. 492 | @end group 493 | @end smallexample 494 | 495 | If you have Invariant Sections without Cover Texts, or some other 496 | combination of the three, merge those two alternatives to suit the 497 | situation. 498 | 499 | If your document contains nontrivial examples of program code, we 500 | recommend releasing these examples in parallel under your choice of 501 | free software license, such as the GNU General Public License, 502 | to permit their use in free software. 503 | 504 | 505 | @c Local Variables: 506 | @c ispell-local-pdict: "ispell-dict" 507 | @c End: 508 | 509 | -------------------------------------------------------------------------------- /doc/gpl.texi: -------------------------------------------------------------------------------- 1 | @c The GNU General Public License. 2 | @center Version 3, 29 June 2007 3 | 4 | @c This file is intended to be included within another document, 5 | @c hence no sectioning command or @node. 6 | 7 | @display 8 | Copyright @copyright{} 2007 Free Software Foundation, Inc. @url{http://fsf.org/} 9 | 10 | Everyone is permitted to copy and distribute verbatim copies of this 11 | license document, but changing it is not allowed. 12 | @end display 13 | 14 | @heading Preamble 15 | 16 | The GNU General Public License is a free, copyleft license for 17 | software and other kinds of works. 18 | 19 | The licenses for most software and other practical works are designed 20 | to take away your freedom to share and change the works. By contrast, 21 | the GNU General Public License is intended to guarantee your freedom 22 | to share and change all versions of a program---to make sure it remains 23 | free software for all its users. We, the Free Software Foundation, 24 | use the GNU General Public License for most of our software; it 25 | applies also to any other work released this way by its authors. You 26 | can apply it to your programs, too. 27 | 28 | When we speak of free software, we are referring to freedom, not 29 | price. Our General Public Licenses are designed to make sure that you 30 | have the freedom to distribute copies of free software (and charge for 31 | them if you wish), that you receive source code or can get it if you 32 | want it, that you can change the software or use pieces of it in new 33 | free programs, and that you know you can do these things. 34 | 35 | To protect your rights, we need to prevent others from denying you 36 | these rights or asking you to surrender the rights. Therefore, you 37 | have certain responsibilities if you distribute copies of the 38 | software, or if you modify it: responsibilities to respect the freedom 39 | of others. 40 | 41 | For example, if you distribute copies of such a program, whether 42 | gratis or for a fee, you must pass on to the recipients the same 43 | freedoms that you received. You must make sure that they, too, 44 | receive or can get the source code. And you must show them these 45 | terms so they know their rights. 46 | 47 | Developers that use the GNU GPL protect your rights with two steps: 48 | (1) assert copyright on the software, and (2) offer you this License 49 | giving you legal permission to copy, distribute and/or modify it. 50 | 51 | For the developers' and authors' protection, the GPL clearly explains 52 | that there is no warranty for this free software. For both users' and 53 | authors' sake, the GPL requires that modified versions be marked as 54 | changed, so that their problems will not be attributed erroneously to 55 | authors of previous versions. 56 | 57 | Some devices are designed to deny users access to install or run 58 | modified versions of the software inside them, although the 59 | manufacturer can do so. This is fundamentally incompatible with the 60 | aim of protecting users' freedom to change the software. The 61 | systematic pattern of such abuse occurs in the area of products for 62 | individuals to use, which is precisely where it is most unacceptable. 63 | Therefore, we have designed this version of the GPL to prohibit the 64 | practice for those products. If such problems arise substantially in 65 | other domains, we stand ready to extend this provision to those 66 | domains in future versions of the GPL, as needed to protect the 67 | freedom of users. 68 | 69 | Finally, every program is threatened constantly by software patents. 70 | States should not allow patents to restrict development and use of 71 | software on general-purpose computers, but in those that do, we wish 72 | to avoid the special danger that patents applied to a free program 73 | could make it effectively proprietary. To prevent this, the GPL 74 | assures that patents cannot be used to render the program non-free. 75 | 76 | The precise terms and conditions for copying, distribution and 77 | modification follow. 78 | 79 | @heading TERMS AND CONDITIONS 80 | 81 | @enumerate 0 82 | @item Definitions. 83 | 84 | ``This License'' refers to version 3 of the GNU General Public License. 85 | 86 | ``Copyright'' also means copyright-like laws that apply to other kinds 87 | of works, such as semiconductor masks. 88 | 89 | ``The Program'' refers to any copyrightable work licensed under this 90 | License. Each licensee is addressed as ``you''. ``Licensees'' and 91 | ``recipients'' may be individuals or organizations. 92 | 93 | To ``modify'' a work means to copy from or adapt all or part of the work 94 | in a fashion requiring copyright permission, other than the making of 95 | an exact copy. The resulting work is called a ``modified version'' of 96 | the earlier work or a work ``based on'' the earlier work. 97 | 98 | A ``covered work'' means either the unmodified Program or a work based 99 | on the Program. 100 | 101 | To ``propagate'' a work means to do anything with it that, without 102 | permission, would make you directly or secondarily liable for 103 | infringement under applicable copyright law, except executing it on a 104 | computer or modifying a private copy. Propagation includes copying, 105 | distribution (with or without modification), making available to the 106 | public, and in some countries other activities as well. 107 | 108 | To ``convey'' a work means any kind of propagation that enables other 109 | parties to make or receive copies. Mere interaction with a user 110 | through a computer network, with no transfer of a copy, is not 111 | conveying. 112 | 113 | An interactive user interface displays ``Appropriate Legal Notices'' to 114 | the extent that it includes a convenient and prominently visible 115 | feature that (1) displays an appropriate copyright notice, and (2) 116 | tells the user that there is no warranty for the work (except to the 117 | extent that warranties are provided), that licensees may convey the 118 | work under this License, and how to view a copy of this License. If 119 | the interface presents a list of user commands or options, such as a 120 | menu, a prominent item in the list meets this criterion. 121 | 122 | @item Source Code. 123 | 124 | The ``source code'' for a work means the preferred form of the work for 125 | making modifications to it. ``Object code'' means any non-source form 126 | of a work. 127 | 128 | A ``Standard Interface'' means an interface that either is an official 129 | standard defined by a recognized standards body, or, in the case of 130 | interfaces specified for a particular programming language, one that 131 | is widely used among developers working in that language. 132 | 133 | The ``System Libraries'' of an executable work include anything, other 134 | than the work as a whole, that (a) is included in the normal form of 135 | packaging a Major Component, but which is not part of that Major 136 | Component, and (b) serves only to enable use of the work with that 137 | Major Component, or to implement a Standard Interface for which an 138 | implementation is available to the public in source code form. A 139 | ``Major Component'', in this context, means a major essential component 140 | (kernel, window system, and so on) of the specific operating system 141 | (if any) on which the executable work runs, or a compiler used to 142 | produce the work, or an object code interpreter used to run it. 143 | 144 | The ``Corresponding Source'' for a work in object code form means all 145 | the source code needed to generate, install, and (for an executable 146 | work) run the object code and to modify the work, including scripts to 147 | control those activities. However, it does not include the work's 148 | System Libraries, or general-purpose tools or generally available free 149 | programs which are used unmodified in performing those activities but 150 | which are not part of the work. For example, Corresponding Source 151 | includes interface definition files associated with source files for 152 | the work, and the source code for shared libraries and dynamically 153 | linked subprograms that the work is specifically designed to require, 154 | such as by intimate data communication or control flow between those 155 | subprograms and other parts of the work. 156 | 157 | The Corresponding Source need not include anything that users can 158 | regenerate automatically from other parts of the Corresponding Source. 159 | 160 | The Corresponding Source for a work in source code form is that same 161 | work. 162 | 163 | @item Basic Permissions. 164 | 165 | All rights granted under this License are granted for the term of 166 | copyright on the Program, and are irrevocable provided the stated 167 | conditions are met. This License explicitly affirms your unlimited 168 | permission to run the unmodified Program. The output from running a 169 | covered work is covered by this License only if the output, given its 170 | content, constitutes a covered work. This License acknowledges your 171 | rights of fair use or other equivalent, as provided by copyright law. 172 | 173 | You may make, run and propagate covered works that you do not convey, 174 | without conditions so long as your license otherwise remains in force. 175 | You may convey covered works to others for the sole purpose of having 176 | them make modifications exclusively for you, or provide you with 177 | facilities for running those works, provided that you comply with the 178 | terms of this License in conveying all material for which you do not 179 | control copyright. Those thus making or running the covered works for 180 | you must do so exclusively on your behalf, under your direction and 181 | control, on terms that prohibit them from making any copies of your 182 | copyrighted material outside their relationship with you. 183 | 184 | Conveying under any other circumstances is permitted solely under the 185 | conditions stated below. Sublicensing is not allowed; section 10 186 | makes it unnecessary. 187 | 188 | @item Protecting Users' Legal Rights From Anti-Circumvention Law. 189 | 190 | No covered work shall be deemed part of an effective technological 191 | measure under any applicable law fulfilling obligations under article 192 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 193 | similar laws prohibiting or restricting circumvention of such 194 | measures. 195 | 196 | When you convey a covered work, you waive any legal power to forbid 197 | circumvention of technological measures to the extent such 198 | circumvention is effected by exercising rights under this License with 199 | respect to the covered work, and you disclaim any intention to limit 200 | operation or modification of the work as a means of enforcing, against 201 | the work's users, your or third parties' legal rights to forbid 202 | circumvention of technological measures. 203 | 204 | @item Conveying Verbatim Copies. 205 | 206 | You may convey verbatim copies of the Program's source code as you 207 | receive it, in any medium, provided that you conspicuously and 208 | appropriately publish on each copy an appropriate copyright notice; 209 | keep intact all notices stating that this License and any 210 | non-permissive terms added in accord with section 7 apply to the code; 211 | keep intact all notices of the absence of any warranty; and give all 212 | recipients a copy of this License along with the Program. 213 | 214 | You may charge any price or no price for each copy that you convey, 215 | and you may offer support or warranty protection for a fee. 216 | 217 | @item Conveying Modified Source Versions. 218 | 219 | You may convey a work based on the Program, or the modifications to 220 | produce it from the Program, in the form of source code under the 221 | terms of section 4, provided that you also meet all of these 222 | conditions: 223 | 224 | @enumerate a 225 | @item 226 | The work must carry prominent notices stating that you modified it, 227 | and giving a relevant date. 228 | 229 | @item 230 | The work must carry prominent notices stating that it is released 231 | under this License and any conditions added under section 7. This 232 | requirement modifies the requirement in section 4 to ``keep intact all 233 | notices''. 234 | 235 | @item 236 | You must license the entire work, as a whole, under this License to 237 | anyone who comes into possession of a copy. This License will 238 | therefore apply, along with any applicable section 7 additional terms, 239 | to the whole of the work, and all its parts, regardless of how they 240 | are packaged. This License gives no permission to license the work in 241 | any other way, but it does not invalidate such permission if you have 242 | separately received it. 243 | 244 | @item 245 | If the work has interactive user interfaces, each must display 246 | Appropriate Legal Notices; however, if the Program has interactive 247 | interfaces that do not display Appropriate Legal Notices, your work 248 | need not make them do so. 249 | @end enumerate 250 | 251 | A compilation of a covered work with other separate and independent 252 | works, which are not by their nature extensions of the covered work, 253 | and which are not combined with it such as to form a larger program, 254 | in or on a volume of a storage or distribution medium, is called an 255 | ``aggregate'' if the compilation and its resulting copyright are not 256 | used to limit the access or legal rights of the compilation's users 257 | beyond what the individual works permit. Inclusion of a covered work 258 | in an aggregate does not cause this License to apply to the other 259 | parts of the aggregate. 260 | 261 | @item Conveying Non-Source Forms. 262 | 263 | You may convey a covered work in object code form under the terms of 264 | sections 4 and 5, provided that you also convey the machine-readable 265 | Corresponding Source under the terms of this License, in one of these 266 | ways: 267 | 268 | @enumerate a 269 | @item 270 | Convey the object code in, or embodied in, a physical product 271 | (including a physical distribution medium), accompanied by the 272 | Corresponding Source fixed on a durable physical medium customarily 273 | used for software interchange. 274 | 275 | @item 276 | Convey the object code in, or embodied in, a physical product 277 | (including a physical distribution medium), accompanied by a written 278 | offer, valid for at least three years and valid for as long as you 279 | offer spare parts or customer support for that product model, to give 280 | anyone who possesses the object code either (1) a copy of the 281 | Corresponding Source for all the software in the product that is 282 | covered by this License, on a durable physical medium customarily used 283 | for software interchange, for a price no more than your reasonable 284 | cost of physically performing this conveying of source, or (2) access 285 | to copy the Corresponding Source from a network server at no charge. 286 | 287 | @item 288 | Convey individual copies of the object code with a copy of the written 289 | offer to provide the Corresponding Source. This alternative is 290 | allowed only occasionally and noncommercially, and only if you 291 | received the object code with such an offer, in accord with subsection 292 | 6b. 293 | 294 | @item 295 | Convey the object code by offering access from a designated place 296 | (gratis or for a charge), and offer equivalent access to the 297 | Corresponding Source in the same way through the same place at no 298 | further charge. You need not require recipients to copy the 299 | Corresponding Source along with the object code. If the place to copy 300 | the object code is a network server, the Corresponding Source may be 301 | on a different server (operated by you or a third party) that supports 302 | equivalent copying facilities, provided you maintain clear directions 303 | next to the object code saying where to find the Corresponding Source. 304 | Regardless of what server hosts the Corresponding Source, you remain 305 | obligated to ensure that it is available for as long as needed to 306 | satisfy these requirements. 307 | 308 | @item 309 | Convey the object code using peer-to-peer transmission, provided you 310 | inform other peers where the object code and Corresponding Source of 311 | the work are being offered to the general public at no charge under 312 | subsection 6d. 313 | 314 | @end enumerate 315 | 316 | A separable portion of the object code, whose source code is excluded 317 | from the Corresponding Source as a System Library, need not be 318 | included in conveying the object code work. 319 | 320 | A ``User Product'' is either (1) a ``consumer product'', which means any 321 | tangible personal property which is normally used for personal, 322 | family, or household purposes, or (2) anything designed or sold for 323 | incorporation into a dwelling. In determining whether a product is a 324 | consumer product, doubtful cases shall be resolved in favor of 325 | coverage. For a particular product received by a particular user, 326 | ``normally used'' refers to a typical or common use of that class of 327 | product, regardless of the status of the particular user or of the way 328 | in which the particular user actually uses, or expects or is expected 329 | to use, the product. A product is a consumer product regardless of 330 | whether the product has substantial commercial, industrial or 331 | non-consumer uses, unless such uses represent the only significant 332 | mode of use of the product. 333 | 334 | ``Installation Information'' for a User Product means any methods, 335 | procedures, authorization keys, or other information required to 336 | install and execute modified versions of a covered work in that User 337 | Product from a modified version of its Corresponding Source. The 338 | information must suffice to ensure that the continued functioning of 339 | the modified object code is in no case prevented or interfered with 340 | solely because modification has been made. 341 | 342 | If you convey an object code work under this section in, or with, or 343 | specifically for use in, a User Product, and the conveying occurs as 344 | part of a transaction in which the right of possession and use of the 345 | User Product is transferred to the recipient in perpetuity or for a 346 | fixed term (regardless of how the transaction is characterized), the 347 | Corresponding Source conveyed under this section must be accompanied 348 | by the Installation Information. But this requirement does not apply 349 | if neither you nor any third party retains the ability to install 350 | modified object code on the User Product (for example, the work has 351 | been installed in ROM). 352 | 353 | The requirement to provide Installation Information does not include a 354 | requirement to continue to provide support service, warranty, or 355 | updates for a work that has been modified or installed by the 356 | recipient, or for the User Product in which it has been modified or 357 | installed. Access to a network may be denied when the modification 358 | itself materially and adversely affects the operation of the network 359 | or violates the rules and protocols for communication across the 360 | network. 361 | 362 | Corresponding Source conveyed, and Installation Information provided, 363 | in accord with this section must be in a format that is publicly 364 | documented (and with an implementation available to the public in 365 | source code form), and must require no special password or key for 366 | unpacking, reading or copying. 367 | 368 | @item Additional Terms. 369 | 370 | ``Additional permissions'' are terms that supplement the terms of this 371 | License by making exceptions from one or more of its conditions. 372 | Additional permissions that are applicable to the entire Program shall 373 | be treated as though they were included in this License, to the extent 374 | that they are valid under applicable law. If additional permissions 375 | apply only to part of the Program, that part may be used separately 376 | under those permissions, but the entire Program remains governed by 377 | this License without regard to the additional permissions. 378 | 379 | When you convey a copy of a covered work, you may at your option 380 | remove any additional permissions from that copy, or from any part of 381 | it. (Additional permissions may be written to require their own 382 | removal in certain cases when you modify the work.) You may place 383 | additional permissions on material, added by you to a covered work, 384 | for which you have or can give appropriate copyright permission. 385 | 386 | Notwithstanding any other provision of this License, for material you 387 | add to a covered work, you may (if authorized by the copyright holders 388 | of that material) supplement the terms of this License with terms: 389 | 390 | @enumerate a 391 | @item 392 | Disclaiming warranty or limiting liability differently from the terms 393 | of sections 15 and 16 of this License; or 394 | 395 | @item 396 | Requiring preservation of specified reasonable legal notices or author 397 | attributions in that material or in the Appropriate Legal Notices 398 | displayed by works containing it; or 399 | 400 | @item 401 | Prohibiting misrepresentation of the origin of that material, or 402 | requiring that modified versions of such material be marked in 403 | reasonable ways as different from the original version; or 404 | 405 | @item 406 | Limiting the use for publicity purposes of names of licensors or 407 | authors of the material; or 408 | 409 | @item 410 | Declining to grant rights under trademark law for use of some trade 411 | names, trademarks, or service marks; or 412 | 413 | @item 414 | Requiring indemnification of licensors and authors of that material by 415 | anyone who conveys the material (or modified versions of it) with 416 | contractual assumptions of liability to the recipient, for any 417 | liability that these contractual assumptions directly impose on those 418 | licensors and authors. 419 | @end enumerate 420 | 421 | All other non-permissive additional terms are considered ``further 422 | restrictions'' within the meaning of section 10. If the Program as you 423 | received it, or any part of it, contains a notice stating that it is 424 | governed by this License along with a term that is a further 425 | restriction, you may remove that term. If a license document contains 426 | a further restriction but permits relicensing or conveying under this 427 | License, you may add to a covered work material governed by the terms 428 | of that license document, provided that the further restriction does 429 | not survive such relicensing or conveying. 430 | 431 | If you add terms to a covered work in accord with this section, you 432 | must place, in the relevant source files, a statement of the 433 | additional terms that apply to those files, or a notice indicating 434 | where to find the applicable terms. 435 | 436 | Additional terms, permissive or non-permissive, may be stated in the 437 | form of a separately written license, or stated as exceptions; the 438 | above requirements apply either way. 439 | 440 | @item Termination. 441 | 442 | You may not propagate or modify a covered work except as expressly 443 | provided under this License. Any attempt otherwise to propagate or 444 | modify it is void, and will automatically terminate your rights under 445 | this License (including any patent licenses granted under the third 446 | paragraph of section 11). 447 | 448 | However, if you cease all violation of this License, then your license 449 | from a particular copyright holder is reinstated (a) provisionally, 450 | unless and until the copyright holder explicitly and finally 451 | terminates your license, and (b) permanently, if the copyright holder 452 | fails to notify you of the violation by some reasonable means prior to 453 | 60 days after the cessation. 454 | 455 | Moreover, your license from a particular copyright holder is 456 | reinstated permanently if the copyright holder notifies you of the 457 | violation by some reasonable means, this is the first time you have 458 | received notice of violation of this License (for any work) from that 459 | copyright holder, and you cure the violation prior to 30 days after 460 | your receipt of the notice. 461 | 462 | Termination of your rights under this section does not terminate the 463 | licenses of parties who have received copies or rights from you under 464 | this License. If your rights have been terminated and not permanently 465 | reinstated, you do not qualify to receive new licenses for the same 466 | material under section 10. 467 | 468 | @item Acceptance Not Required for Having Copies. 469 | 470 | You are not required to accept this License in order to receive or run 471 | a copy of the Program. Ancillary propagation of a covered work 472 | occurring solely as a consequence of using peer-to-peer transmission 473 | to receive a copy likewise does not require acceptance. However, 474 | nothing other than this License grants you permission to propagate or 475 | modify any covered work. These actions infringe copyright if you do 476 | not accept this License. Therefore, by modifying or propagating a 477 | covered work, you indicate your acceptance of this License to do so. 478 | 479 | @item Automatic Licensing of Downstream Recipients. 480 | 481 | Each time you convey a covered work, the recipient automatically 482 | receives a license from the original licensors, to run, modify and 483 | propagate that work, subject to this License. You are not responsible 484 | for enforcing compliance by third parties with this License. 485 | 486 | An ``entity transaction'' is a transaction transferring control of an 487 | organization, or substantially all assets of one, or subdividing an 488 | organization, or merging organizations. If propagation of a covered 489 | work results from an entity transaction, each party to that 490 | transaction who receives a copy of the work also receives whatever 491 | licenses to the work the party's predecessor in interest had or could 492 | give under the previous paragraph, plus a right to possession of the 493 | Corresponding Source of the work from the predecessor in interest, if 494 | the predecessor has it or can get it with reasonable efforts. 495 | 496 | You may not impose any further restrictions on the exercise of the 497 | rights granted or affirmed under this License. For example, you may 498 | not impose a license fee, royalty, or other charge for exercise of 499 | rights granted under this License, and you may not initiate litigation 500 | (including a cross-claim or counterclaim in a lawsuit) alleging that 501 | any patent claim is infringed by making, using, selling, offering for 502 | sale, or importing the Program or any portion of it. 503 | 504 | @item Patents. 505 | 506 | A ``contributor'' is a copyright holder who authorizes use under this 507 | License of the Program or a work on which the Program is based. The 508 | work thus licensed is called the contributor's ``contributor version''. 509 | 510 | A contributor's ``essential patent claims'' are all patent claims owned 511 | or controlled by the contributor, whether already acquired or 512 | hereafter acquired, that would be infringed by some manner, permitted 513 | by this License, of making, using, or selling its contributor version, 514 | but do not include claims that would be infringed only as a 515 | consequence of further modification of the contributor version. For 516 | purposes of this definition, ``control'' includes the right to grant 517 | patent sublicenses in a manner consistent with the requirements of 518 | this License. 519 | 520 | Each contributor grants you a non-exclusive, worldwide, royalty-free 521 | patent license under the contributor's essential patent claims, to 522 | make, use, sell, offer for sale, import and otherwise run, modify and 523 | propagate the contents of its contributor version. 524 | 525 | In the following three paragraphs, a ``patent license'' is any express 526 | agreement or commitment, however denominated, not to enforce a patent 527 | (such as an express permission to practice a patent or covenant not to 528 | sue for patent infringement). To ``grant'' such a patent license to a 529 | party means to make such an agreement or commitment not to enforce a 530 | patent against the party. 531 | 532 | If you convey a covered work, knowingly relying on a patent license, 533 | and the Corresponding Source of the work is not available for anyone 534 | to copy, free of charge and under the terms of this License, through a 535 | publicly available network server or other readily accessible means, 536 | then you must either (1) cause the Corresponding Source to be so 537 | available, or (2) arrange to deprive yourself of the benefit of the 538 | patent license for this particular work, or (3) arrange, in a manner 539 | consistent with the requirements of this License, to extend the patent 540 | license to downstream recipients. ``Knowingly relying'' means you have 541 | actual knowledge that, but for the patent license, your conveying the 542 | covered work in a country, or your recipient's use of the covered work 543 | in a country, would infringe one or more identifiable patents in that 544 | country that you have reason to believe are valid. 545 | 546 | If, pursuant to or in connection with a single transaction or 547 | arrangement, you convey, or propagate by procuring conveyance of, a 548 | covered work, and grant a patent license to some of the parties 549 | receiving the covered work authorizing them to use, propagate, modify 550 | or convey a specific copy of the covered work, then the patent license 551 | you grant is automatically extended to all recipients of the covered 552 | work and works based on it. 553 | 554 | A patent license is ``discriminatory'' if it does not include within the 555 | scope of its coverage, prohibits the exercise of, or is conditioned on 556 | the non-exercise of one or more of the rights that are specifically 557 | granted under this License. You may not convey a covered work if you 558 | are a party to an arrangement with a third party that is in the 559 | business of distributing software, under which you make payment to the 560 | third party based on the extent of your activity of conveying the 561 | work, and under which the third party grants, to any of the parties 562 | who would receive the covered work from you, a discriminatory patent 563 | license (a) in connection with copies of the covered work conveyed by 564 | you (or copies made from those copies), or (b) primarily for and in 565 | connection with specific products or compilations that contain the 566 | covered work, unless you entered into that arrangement, or that patent 567 | license was granted, prior to 28 March 2007. 568 | 569 | Nothing in this License shall be construed as excluding or limiting 570 | any implied license or other defenses to infringement that may 571 | otherwise be available to you under applicable patent law. 572 | 573 | @item No Surrender of Others' Freedom. 574 | 575 | If conditions are imposed on you (whether by court order, agreement or 576 | otherwise) that contradict the conditions of this License, they do not 577 | excuse you from the conditions of this License. If you cannot convey 578 | a covered work so as to satisfy simultaneously your obligations under 579 | this License and any other pertinent obligations, then as a 580 | consequence you may not convey it at all. For example, if you agree 581 | to terms that obligate you to collect a royalty for further conveying 582 | from those to whom you convey the Program, the only way you could 583 | satisfy both those terms and this License would be to refrain entirely 584 | from conveying the Program. 585 | 586 | @item Use with the GNU Affero General Public License. 587 | 588 | Notwithstanding any other provision of this License, you have 589 | permission to link or combine any covered work with a work licensed 590 | under version 3 of the GNU Affero General Public License into a single 591 | combined work, and to convey the resulting work. The terms of this 592 | License will continue to apply to the part which is the covered work, 593 | but the special requirements of the GNU Affero General Public License, 594 | section 13, concerning interaction through a network will apply to the 595 | combination as such. 596 | 597 | @item Revised Versions of this License. 598 | 599 | The Free Software Foundation may publish revised and/or new versions 600 | of the GNU General Public License from time to time. Such new 601 | versions will be similar in spirit to the present version, but may 602 | differ in detail to address new problems or concerns. 603 | 604 | Each version is given a distinguishing version number. If the Program 605 | specifies that a certain numbered version of the GNU General Public 606 | License ``or any later version'' applies to it, you have the option of 607 | following the terms and conditions either of that numbered version or 608 | of any later version published by the Free Software Foundation. If 609 | the Program does not specify a version number of the GNU General 610 | Public License, you may choose any version ever published by the Free 611 | Software Foundation. 612 | 613 | If the Program specifies that a proxy can decide which future versions 614 | of the GNU General Public License can be used, that proxy's public 615 | statement of acceptance of a version permanently authorizes you to 616 | choose that version for the Program. 617 | 618 | Later license versions may give you additional or different 619 | permissions. However, no additional obligations are imposed on any 620 | author or copyright holder as a result of your choosing to follow a 621 | later version. 622 | 623 | @item Disclaimer of Warranty. 624 | 625 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 626 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 627 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT 628 | WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 629 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 630 | A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 631 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 632 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 633 | CORRECTION. 634 | 635 | @item Limitation of Liability. 636 | 637 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 638 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR 639 | CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 640 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 641 | ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT 642 | NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 643 | LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM 644 | TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 645 | PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 646 | 647 | @item Interpretation of Sections 15 and 16. 648 | 649 | If the disclaimer of warranty and limitation of liability provided 650 | above cannot be given local legal effect according to their terms, 651 | reviewing courts shall apply local law that most closely approximates 652 | an absolute waiver of all civil liability in connection with the 653 | Program, unless a warranty or assumption of liability accompanies a 654 | copy of the Program in return for a fee. 655 | 656 | @end enumerate 657 | 658 | @heading END OF TERMS AND CONDITIONS 659 | 660 | @heading How to Apply These Terms to Your New Programs 661 | 662 | If you develop a new program, and you want it to be of the greatest 663 | possible use to the public, the best way to achieve this is to make it 664 | free software which everyone can redistribute and change under these 665 | terms. 666 | 667 | To do so, attach the following notices to the program. It is safest 668 | to attach them to the start of each source file to most effectively 669 | state the exclusion of warranty; and each file should have at least 670 | the ``copyright'' line and a pointer to where the full notice is found. 671 | 672 | @smallexample 673 | @var{one line to give the program's name and a brief idea of what it does.} 674 | Copyright (C) @var{year} @var{name of author} 675 | 676 | This program is free software: you can redistribute it and/or modify 677 | it under the terms of the GNU General Public License as published by 678 | the Free Software Foundation, either version 3 of the License, or (at 679 | your option) any later version. 680 | 681 | This program is distributed in the hope that it will be useful, but 682 | WITHOUT ANY WARRANTY; without even the implied warranty of 683 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 684 | General Public License for more details. 685 | 686 | You should have received a copy of the GNU General Public License 687 | along with this program. If not, see @url{http://www.gnu.org/licenses/}. 688 | @end smallexample 689 | 690 | Also add information on how to contact you by electronic and paper mail. 691 | 692 | If the program does terminal interaction, make it output a short 693 | notice like this when it starts in an interactive mode: 694 | 695 | @smallexample 696 | @var{program} Copyright (C) @var{year} @var{name of author} 697 | This program comes with ABSOLUTELY NO WARRANTY; for details type @samp{show w}. 698 | This is free software, and you are welcome to redistribute it 699 | under certain conditions; type @samp{show c} for details. 700 | @end smallexample 701 | 702 | The hypothetical commands @samp{show w} and @samp{show c} should show 703 | the appropriate parts of the General Public License. Of course, your 704 | program's commands might be different; for a GUI interface, you would 705 | use an ``about box''. 706 | 707 | You should also get your employer (if you work as a programmer) or school, 708 | if any, to sign a ``copyright disclaimer'' for the program, if necessary. 709 | For more information on this, and how to apply and follow the GNU GPL, see 710 | @url{http://www.gnu.org/licenses/}. 711 | 712 | The GNU General Public License does not permit incorporating your 713 | program into proprietary programs. If your program is a subroutine 714 | library, you may consider it more useful to permit linking proprietary 715 | applications with the library. If this is what you want to do, use 716 | the GNU Lesser General Public License instead of this License. But 717 | first, please read @url{http://www.gnu.org/philosophy/why-not-lgpl.html}. 718 | -------------------------------------------------------------------------------- /doc/web-server.texi: -------------------------------------------------------------------------------- 1 | \input texinfo 2 | @c @setfilename emacs-web-server.info 3 | @documentencoding utf-8 4 | @settitle Emacs Web Server (web-server) User Manual 5 | 6 | @copying 7 | This file documents the Emacs Web Server (web-server) 8 | 9 | Copyright (C) 2013 Eric Schulte 10 | 11 | @quotation 12 | Permission is granted to copy, distribute and/or modify this document 13 | under the terms of the GNU Free Documentation License, Version 1.3 14 | or any later version published by the Free Software Foundation; 15 | with the Invariant Section being ``GNU GENERAL PUBLIC LICENSE,'' 16 | A copy of the license is included in the section entitled 17 | ``GNU Free Documentation License.'' 18 | @end quotation 19 | @end copying 20 | 21 | @dircategory Emacs 22 | @direntry 23 | * Web Server: (web-server). Web Server for Emacs. 24 | @end direntry 25 | 26 | @titlepage 27 | @title Emacs Web Server (web-server) User Manual 28 | @page 29 | @vskip 0pt plus 1filll 30 | @insertcopying 31 | @end titlepage 32 | 33 | @c Output the table of the contents at the beginning. 34 | @contents 35 | 36 | @ifnottex 37 | @node Top, Introduction, (dir), (dir) 38 | @top Emacs Web Server User Manual 39 | 40 | @insertcopying 41 | @end ifnottex 42 | 43 | @menu 44 | * Introduction:: Overview of the Emacs Web Server 45 | * Handlers:: Handlers respond to HTTP requests 46 | * Requests:: Getting information on HTTP requests 47 | * Usage Examples:: Examples demonstrating usage 48 | * Function Index:: List of Functions 49 | 50 | Appendices 51 | 52 | * Copying:: The GNU General Public License gives 53 | you permission to redistribute GNU Emacs on 54 | certain terms; it also explains that there is 55 | no warranty. 56 | * GNU Free Documentation License:: The license for this documentation. 57 | * Index:: Complete index. 58 | 59 | 60 | 61 | 62 | @end menu 63 | 64 | @node Introduction, Handlers, Top, Top 65 | @chapter Introduction 66 | @cindex introduction 67 | 68 | The Emacs Web Server is a Web server implemented entirely in Emacs 69 | Lisp. HTTP requests are matched to handlers (@pxref{Handlers}) which 70 | are Emacs Lisp functions. Handlers receive as their only argument a 71 | request object (@pxref{Requests}) which holds information about the 72 | request and a process holding the HTTP network connection. Handlers 73 | write their responses directly to the network process. 74 | 75 | A number of examples (@pxref{Usage Examples}) demonstrate usage of the 76 | Emacs Web Server. All public functions of the Emacs Web Server are 77 | listed (@pxref{Function Index}). 78 | 79 | @node Handlers, Requests, Handlers, Top 80 | @chapter Handlers 81 | @cindex handlers 82 | 83 | The function @code{ws-start} takes takes two arguments @code{handlers} 84 | and @code{port}. It starts a server listening on @code{port} 85 | responding to requests with @code{handlers}. @code{Handlers} may be 86 | either a single function or an association list composed of pairs of 87 | matchers and handler functions. When @code{handlers} is a single 88 | function the given function is used to serve every request, when it is 89 | an association list, the function of the first matcher to match each 90 | request handles that request. 91 | 92 | @section Matchers 93 | @cindex matchers 94 | 95 | Matchers may be a regular expression or a function. Regular 96 | expression matchers consists of an HTTP header and a regular 97 | expression. When the regular expression matches the content of the 98 | given header the matcher succeeds and the associated handler is 99 | called. For example the following matches any @code{GET} request 100 | whose path starts with the substring ``foo''. 101 | 102 | @example 103 | (:GET . "^foo") 104 | @end example 105 | 106 | A function matcher is a function which takes the request object 107 | (@pxref{Requests}) and succeeds when the function returns a non-nil 108 | value. For example the following matcher matches every request, 109 | 110 | @example 111 | (lambda (_) t) 112 | @end example 113 | 114 | and the following matches only requests in which the supplied 115 | ``number'' parameter is odd. 116 | 117 | @example 118 | (lambda (request) 119 | (oddp (string-to-number (cdr (assoc "number" request))))) 120 | @end example 121 | 122 | @section Handler Function 123 | @cindex handler function 124 | 125 | Each handler is a function which takes a request object 126 | (@pxref{Requests}) as its only argument. The function may respond to 127 | the request by writing to the network process held in the 128 | @code{process} field of the request object. For example, the 129 | @code{process-send-string} function may be used to write string data 130 | to a request as in the following. 131 | 132 | @example 133 | (process-send-string (process request) "hello world") 134 | @end example 135 | 136 | When the handler function exits the connection is terminated unless 137 | the handler function returns the keyword @code{:keep-alive}. 138 | 139 | @node Requests, Usage Examples, Handlers, Top 140 | @chapter Requests 141 | @cindex requests 142 | 143 | Each HTTP requests is represented using a @code{ws-request} object 144 | (@pxref{ws-request}). The request object serves two purposes, one 145 | internal and one external. Internally, request objects are used to 146 | hold state while HTTP headers are parsed incrementally as the HTTP 147 | request text is received from the network. Externally, request 148 | objects are used to decide which handler to call, and are then passed 149 | as the only argument to the called handler. 150 | 151 | In addition to fields used internally, each @code{ws-request} object 152 | holds the network process in the @code{process} and holds all HTTP 153 | headers and request GET or POST parameters in the @code{headers} 154 | alist. HTML Headers are keyed using uppercase keywords (e.g., 155 | @code{:GET}), and user supplied parameters are keyed using the string 156 | name of the parameter. 157 | 158 | The @code{process} field may be used by handlers to send data to a 159 | client as in the following example. 160 | 161 | @example 162 | (process-send-string (process request) "hello world") 163 | @end example 164 | 165 | The @code{headers} field may be used to access request information 166 | such as the requested path, 167 | 168 | @example 169 | (cdr (assoc :GET (headers request))) 170 | @end example 171 | 172 | or named parameters as from a web form. 173 | 174 | @example 175 | (cdr (assoc "message" (headers request))) 176 | @end example 177 | 178 | @node Usage Examples, Hello World, Requests, Top 179 | @chapter Usage Examples 180 | @cindex usage examples 181 | 182 | These examples demonstrate usage. 183 | @menu 184 | * Hello World:: Serve ``Hello World'' to every request 185 | * Hello World UTF8:: Serve ``Hello World'' w/UTF8 encoding 186 | * Hello World HTML:: Serve ``Hello World'' in HTML 187 | * File Server:: Serve files from a document root 188 | * URL Parameter Echo:: Echo parameters from a URL query string 189 | * POST Echo:: Echo POST parameters back 190 | * Basic Authentication:: BASIC HTTP authentication 191 | * Org-mode Export:: Export files to HTML and Tex 192 | * File Upload:: Upload files and return their sha1sum 193 | * Web Socket:: Web socket echo server 194 | * Gzipped Transfer Encoding:: Gzip content encoding 195 | * Chunked Transfer Encoding:: Chunked transfer encoding 196 | @end menu 197 | 198 | @node Hello World, Hello World UTF8, Usage Examples, Usage Examples 199 | @section Hello World 200 | 201 | The simplest possible ``hello world'' example. The handler consists 202 | of a single (matcher . handler) pair. The function matcher matches 203 | @emph{every} incoming HTTP request. The handler responds by setting 204 | the content type to @code{text/plain}, and then sending the string 205 | ``hello world''. When the handler exits the network connection of the 206 | request is closed. 207 | 208 | @verbatiminclude ../examples/000-hello-world.el 209 | 210 | @node Hello World UTF8, Hello World HTML, Hello World, Usage Examples 211 | @section Hello World UTF8 212 | 213 | This example only differs from the previous in that the 214 | ``Content-type'' indicates UTF8 encoded data, and the hello world sent 215 | is selected at random from a list of different languages. 216 | 217 | @verbatiminclude ../examples/001-hello-world-utf8.el 218 | 219 | @node Hello World HTML, File Server, Hello World UTF8, Usage Examples 220 | @section Hello World HTML 221 | @verbatiminclude ../examples/002-hello-world-html.el 222 | 223 | This variation of the ``hello world'' example sends a @code{text/html} 224 | response instead of a simple @code{text/plain} response. 225 | 226 | @node File Server, URL Parameter Echo, Hello World HTML, Usage Examples 227 | @section File Server 228 | 229 | The following example implements a file server which will serve files 230 | from the @code{docroot} document root set to the current working 231 | directory in this example. Four helper functions are used; 232 | @code{ws-in-directory-p} is used to check if the requested path is 233 | within the document root. If not then @code{ws-send-404} is used to 234 | send a default ``File Not Found''. If so then the file is served with 235 | @code{ws-send-file} (which appropriately sets the mime-type of the 236 | response based on the extension of the file) if it is a file or is 237 | served with @code{ws-send-directory-list} if it is a directory. 238 | 239 | @verbatiminclude ../examples/003-file-server.el 240 | 241 | @node URL Parameter Echo, POST Echo, File Server, Usage Examples 242 | @section URL Parameter Echo 243 | 244 | This example demonstrates access of URL-encoded parameters in a 245 | @code{GET} request. For example the following URL 246 | @url{http://localhost:9005/example?foo=bar&baz=qux} will render as 247 | the following HTML table. 248 | 249 | @multitable @columnfractions .5 .5 250 | @item foo @tab bar 251 | @item baz @tab qux 252 | @end multitable 253 | 254 | @verbatiminclude ../examples/004-url-param-echo.el 255 | 256 | @node POST Echo, Basic Authentication, URL Parameter Echo, Usage Examples 257 | @section POST Echo 258 | 259 | The following example echos back the content of the ``message'' field 260 | in a @code{POST} request. 261 | 262 | @verbatiminclude ../examples/005-post-echo.el 263 | 264 | @node Basic Authentication, Org-mode Export, POST Echo, Usage Examples 265 | @section Basic Authentication 266 | 267 | The following example demonstrates BASIC HTTP authentication. The 268 | handler prompts an unauthenticated client for authentication by 269 | sending a ``WWW-Authenticate'' header. 270 | 271 | @example 272 | (ws-response-header process 401 273 | '("WWW-Authenticate" . "Basic realm=\"example\"") 274 | '("Content-type" . "text/plain")) 275 | @end example 276 | 277 | The client replies by setting the ``Authorization'' HTTP header which 278 | is parsed into a list of the form @code{(PROTOCOL USERNAME 279 | . PASSWORD)}. Currently only BASIC HTTP authentication is supported. 280 | 281 | @noindent 282 | Note: BASIC HTTP authentication passes user credentials in plain text 283 | between the client and the server and should generally only be used 284 | with HTTPS network encryption. While the Emacs web server currently 285 | doesn't support HTTPS network encryption it may be run behind an HTTPS 286 | proxy server (e.g., Apache or Nginx) with HTTPS support. 287 | 288 | @verbatiminclude ../examples/006-basic-authentication.el 289 | 290 | @node Org-mode Export, File Upload, Basic Authentication, Usage Examples 291 | @section Org-mode Export 292 | 293 | The following example exports a directory of Org-mode files as either 294 | text, HTML or LaTeX. The Org-mode export engine is used to export 295 | files on-demand as they are requested. 296 | 297 | @verbatiminclude ../examples/007-org-mode-file-server.el 298 | 299 | @node File Upload, Web Socket, Org-mode Export, Usage Examples 300 | @section File Upload 301 | 302 | The following example demonstrates accessing an uploaded file. This 303 | simple server accesses the file named ``file'' and returns it's 304 | sha1sum and file name. 305 | 306 | @verbatiminclude ../examples/008-file-upload.el 307 | 308 | A file may be uploaded from an HTML form, or using the @code{curl} 309 | program as in the following example. 310 | 311 | @example 312 | $ curl -s -F file=@/usr/share/emacs/24.3/etc/COPYING localhost:9008 313 | 8624bcdae55baeef00cd11d5dfcfa60f68710a02 COPYING 314 | $ sha1sum /usr/share/emacs/24.3/etc/COPYING 315 | 8624bcdae55baeef00cd11d5dfcfa60f68710a02 /usr/share/emacs/24.3/etc/COPYING 316 | @end example 317 | 318 | @node Web Socket, Chunked Transfer Encoding, File Upload, Usage Examples 319 | @section Web Socket 320 | 321 | Example demonstrating the use of web sockets for full duplex 322 | communication between clients and the server. Handlers may use the 323 | @code{ws-web-socket-connect} function (@pxref{ws-web-socket-connect}) 324 | to check for and respond to a web socket upgrade request sent by the 325 | client (as demonstrated with the @code{new WebSocket} JavaScript code 326 | in the example). Upon successfully initializing a web socket 327 | connection the call to @code{ws-web-socket-connect} will return the 328 | web socket network process. This process may then be used by the 329 | server to communicate with the client over the web socket using the 330 | @code{process-send-string} and @code{ws-web-socket-frame} functions. 331 | All web socket communication must be wrapped in frames using the 332 | @code{ws-web-socket-frame} function. 333 | 334 | The handler must pass a function as the second argument to 335 | @code{ws-web-socket-connect}. This function will be called on every 336 | web socket message received from the client. 337 | 338 | @noindent 339 | Note: in order to keep the web socket connection alive the request 340 | handler from which @code{ws-web-socket-connect} is called must return 341 | the @code{:keep-alive} keyword, as demonstrated in the example. 342 | 343 | @verbatiminclude ../examples/009-web-socket.el 344 | 345 | @node Gzipped Transfer Encoding, Chunked Transfer Encoding, Web Socket, Usage Examples 346 | @section Gzipped Transfer Encoding 347 | 348 | HTTP Responses may be compressed by setting the ``gzip'' (or 349 | ``compress'' or ``deflate'') content- or transfer-encoding HTTP 350 | headers in @code{ws-response-header}. Any further data sent to the 351 | process using @code{ws-send} will automatically be appropriately 352 | compressed. 353 | 354 | @verbatiminclude ../examples/016-content-encoding-gzip.el 355 | 356 | @node Chunked Transfer Encoding, Function Index, Web Socket, Usage Examples 357 | @section Chunked Transfer Encoding 358 | 359 | Similarly, HTTP Responses may be sent using the ``chunked'' transfer 360 | encoding by passing the appropriate HTTP header to 361 | @code{ws-response-header}. Any further data sent to the process using 362 | @code{ws-send} will automatically be appropriately encoded for chunked 363 | transfer. 364 | 365 | @verbatiminclude ../examples/017-transfer-encoding-chunked.el 366 | 367 | @node Function Index, Copying, Usage Examples, Top 368 | @chapter Function Index 369 | @cindex function index 370 | 371 | The following functions implement the Emacs Web Server public API. 372 | 373 | @section Objects 374 | The following objects represent web servers and requests. 375 | 376 | @anchor{ws-server} 377 | @deftp Class ws-server handlers process port requests 378 | Every Emacs web server is an instance of the @code{ws-server} class. 379 | Each instance includes the @code{handlers} association list and 380 | @code{port} passed to @code{ws-start}, as well as the server network 381 | @code{process} and a list of all active @code{requests}. 382 | @end deftp 383 | 384 | @anchor{ws-request} 385 | @deftp Class ws-request process pending context boundary index active headers 386 | The @code{ws-request} class represents an active web request. The 387 | @code{process} field holds the network process of the client and may 388 | be used by handlers to respond to requests. The @code{headers} field 389 | holds an alist of information on the request for use by handlers. The 390 | remaining @code{pending}, @code{context}, @code{boundary}, 391 | @code{index} and @code{active} fields are used to maintain header 392 | parsing information across calls to the @code{ws-filter} function. 393 | @end deftp 394 | 395 | @section Starting and Stopping Servers 396 | @cindex start and stop 397 | The following functions start and stop Emacs web servers. The 398 | @code{ws-servers} list holds all running servers. 399 | 400 | @anchor{ws-start} 401 | @defun ws-start handlers port &optional log-buffer &rest network-args 402 | @code{ws-start} starts a server listening on @code{port} using 403 | @code{handlers} (@pxref{Handlers}) to match and respond to requests. 404 | An instance of the @code{ws-server} class is returned. 405 | @end defun 406 | 407 | @anchor{ws-servers} 408 | @defvar ws-servers 409 | The @code{ws-servers} list holds all active Emacs web servers. 410 | @end defvar 411 | 412 | @anchor{ws-stop} 413 | @defun ws-stop server 414 | @code{ws-stop} stops @code{server} deletes all related processes, and 415 | frees the server's port. Evaluate the following to stop all emacs web 416 | servers. 417 | @example 418 | (mapc #'ws-stop ws-servers) 419 | @end example 420 | @end defun 421 | 422 | @anchor{ws-stop-all} 423 | @defun ws-stop-all 424 | @code{ws-stop-all} stops all emacs web servers by mapping 425 | @code{ws-stop} over @code{ws-servers}. 426 | @end defun 427 | 428 | @section Convenience Functions 429 | The following convenience functions automate many common tasks 430 | associated with responding to HTTP requests. 431 | 432 | @anchor{ws-response-header} 433 | @cindex content type 434 | @defun ws-response-header process code &rest headers 435 | Send the headers required to start an HTTP response to @code{proc}. 436 | @code{proc} should be a @code{ws-request} @code{proc} of an active 437 | request. 438 | 439 | For example start a standard 200 ``OK'' HTML response with the 440 | following. 441 | 442 | @example 443 | (ws-response-header process 200 '("Content-type" . "text/html")) 444 | @end example 445 | 446 | The encoding may optionally be set in the HTTP header. Send a UTF8 447 | encoded response with the following. 448 | 449 | @example 450 | (ws-response-header process 200 451 | '("Content-type" . "text/plain; charset=utf-8")) 452 | @end example 453 | 454 | Additionally, when ``Content-Encoding'' or ``Transfer-Encoding'' 455 | headers are supplied any subsequent data written to @code{proc} using 456 | @code{ws-send} will be encoded appropriately including sending the 457 | appropriate data upon the end of transmission for chunked transfer 458 | encoding. 459 | 460 | For example with the header @code{("Content-Encoding" . "gzip")}, any 461 | data subsequently written to @code{proc} using @code{ws-send} will be 462 | compressed using the command specified in @code{ws-gzip-cmd}. See 463 | @ref{Gzipped Transfer Encoding} and @ref{Chunked Transfer Encoding} 464 | for more complete examples. 465 | 466 | @end defun 467 | 468 | @anchor{ws-send} 469 | @defun ws-send proc string 470 | Send @code{string} to process @code{proc}. If any Content or Transfer 471 | encodings are in use, apply them to @code{string} before sending. 472 | @end defun 473 | 474 | @anchor{ws-send-500} 475 | @defun ws-send-500 process &rest msg-and-args 476 | @code{ws-send-500} sends a default 500 ``Internal Server Error'' 477 | response to @code{process}. 478 | @end defun 479 | 480 | @anchor{ws-send-404} 481 | @defun ws-send-404 process &rest msg-and-args 482 | @code{ws-send-500} sends a default 404 ``File Not Found'' response to 483 | @code{process}. 484 | @end defun 485 | 486 | @anchor{ws-send-file} 487 | @defun ws-send-file process path &optional mime-type 488 | @code{ws-send-file} sends the file located at @code{path} to 489 | @code{process}. If the optional @code{mime-type} is not set, then the 490 | mime-type is determined by calling @code{mm-default-file-encoding} on 491 | @code{path} or is set to ``application/octet-stream'' if no mime-type 492 | can be determined. 493 | @end defun 494 | 495 | @anchor{ws-send-directory-list} 496 | @defun ws-send-directory-list process directory &optional match 497 | @code{ws-send-directory-list} sends the a listing of the files located 498 | in @code{directory} to @code{process}. The list is sent as an HTML 499 | list of links to the files. Optional argument @code{match} may be set 500 | to a regular expression, in which case only those files that match are 501 | listed. 502 | @end defun 503 | 504 | @anchor{ws-in-directory-p} 505 | @defun ws-in-directory-p parent path 506 | Check if @code{path} is under the @code{parent} directory. 507 | 508 | @example 509 | (ws-in-directory-p "/tmp/" "pics") 510 | @result{} "/tmp/pics" 511 | 512 | (ws-in-directory-p "/tmp/" "..") 513 | @result{} nil 514 | 515 | (ws-in-directory-p "/tmp/" "~/pics") 516 | @result{} nil 517 | @end example 518 | @end defun 519 | 520 | @anchor{ws-with-authentication} 521 | @defun ws-with-authentication handler credentials &optional realm unauth invalid 522 | Return a version of @code{handler} which is protected by 523 | @code{credentials}. Handler should be a normal handler function 524 | (@pxref{Handlers}) and @code{credentials} should be an association 525 | list of usernames and passwords. 526 | 527 | For example, a server running the following handlers, 528 | 529 | @example 530 | (list (cons '(:GET . ".*") 'view-handler) 531 | (cons '(:POST . ".*") 'edit-handler)) 532 | @end example 533 | 534 | could have authorization added by changing the handlers to the 535 | following. 536 | 537 | @example 538 | (list (cons '(:GET . ".*") view-handler) 539 | (cons '(:POST . ".*") (ws-with-authentication 540 | 'org-ehtml-edit-handler 541 | '(("admin" . "password"))))) 542 | @end example 543 | 544 | @end defun 545 | 546 | @anchor{ws-web-socket-connect} 547 | @defun ws-web-socket-connect request handler 548 | If @code{request} is a web socket upgrade request (indicated by the 549 | presence of the @code{:SEC-WEBSOCKET-KEY} header argument) establish a 550 | web socket connection to the client. Call @code{handler} on web 551 | socket messages received from the client. 552 | 553 | @example 554 | (ws-web-socket-connect request 555 | (lambda (proc string) 556 | (process-send-string proc 557 | (ws-web-socket-frame (concat "you said: " string))))) 558 | @result{} #> 559 | @end example 560 | @end defun 561 | 562 | @section Customization Variables 563 | The following variables may be changed to control the behavior of the 564 | web server. Specifically the @code{ws-*-cmd} variables specify the 565 | command lines used to compress data according to content and or 566 | transfer encoding HTTP headers passed to @ref{ws-response-header}. 567 | 568 | @anchor{ws-compress-cmd} 569 | @defvar ws-compress-cmd 570 | Command used for the ``compress'' Content or Transfer coding. 571 | @end defvar 572 | 573 | @anchor{ws-deflate-cmd} 574 | @defvar ws-deflate-cmd 575 | Command used for the ``deflate'' Content or Transfer coding. 576 | @end defvar 577 | 578 | @anchor{ws-gzip-cmd} 579 | @defvar ws-gzip-cmd 580 | Command used for the ``gzip'' Content or Transfer coding. 581 | @end defvar 582 | 583 | @node Copying, GNU Free Documentation License, Function Index, Top 584 | @appendix GNU GENERAL PUBLIC LICENSE 585 | @include gpl.texi 586 | 587 | @node GNU Free Documentation License, Index, Copying, Top 588 | @appendix GNU Free Documentation License 589 | @include doclicense.texi 590 | 591 | @node Index, , GNU Free Documentation License, Top 592 | @unnumbered Index 593 | 594 | @c Combine all index (function variable type and concept) types into a 595 | @c single index. 596 | @syncodeindex fn cp 597 | @syncodeindex vr cp 598 | @syncodeindex tp cp 599 | @printindex cp 600 | 601 | @bye 602 | -------------------------------------------------------------------------------- /examples/000-hello-world.el: -------------------------------------------------------------------------------- 1 | ;;; hello-world.el --- simple hello world server using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (ws-response-header process 200 '("Content-type" . "text/plain")) 8 | (process-send-string process "hello world"))) 9 | 9000) 10 | -------------------------------------------------------------------------------- /examples/001-hello-world-utf8.el: -------------------------------------------------------------------------------- 1 | ;;; hello-world-utf8.el --- utf8 hello world server using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (let ((hellos '("こんにちは" 8 | "안녕하세요" 9 | "góðan dag" 10 | "Grüßgott" 11 | "hyvää päivää" 12 | "yá'át'ééh" 13 | "Γεια σας" 14 | "Вiтаю" 15 | "გამარჯობა" 16 | "नमस्ते" 17 | "你好"))) 18 | (ws-response-header process 200 19 | '("Content-type" . "text/plain; charset=utf-8")) 20 | (process-send-string process 21 | (concat (nth (random (length hellos)) hellos) " world"))))) 22 | 9001) 23 | -------------------------------------------------------------------------------- /examples/002-hello-world-html.el: -------------------------------------------------------------------------------- 1 | ;;; hello-world-html.el --- html hello world server using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (ws-response-header process 200 '("Content-type" . "text/html")) 8 | (process-send-string process " 9 | 10 | Hello World 11 | 12 | 13 | hello world 14 | 15 | "))) 16 | 9002) 17 | -------------------------------------------------------------------------------- /examples/003-file-server.el: -------------------------------------------------------------------------------- 1 | ;;; file-server.el --- serve any files using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (lexical-let ((docroot default-directory)) 5 | (ws-start 6 | (lambda (request) 7 | (with-slots (process headers) request 8 | (let ((path (substring (cdr (assoc :GET headers)) 1))) 9 | (if (ws-in-directory-p docroot path) 10 | (if (file-directory-p path) 11 | (ws-send-directory-list process 12 | (expand-file-name path docroot) "^[^\.]") 13 | (ws-send-file process (expand-file-name path docroot))) 14 | (ws-send-404 process))))) 15 | 9003)) 16 | -------------------------------------------------------------------------------- /examples/004-url-param-echo.el: -------------------------------------------------------------------------------- 1 | ;;; url-param-echo.el --- echo back url-paramed message using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | '(((:GET . ".*") . 6 | (lambda (request) 7 | (with-slots (process headers) request 8 | (ws-response-header process 200 '("Content-type" . "text/html")) 9 | (process-send-string process 10 | (concat "URL Parameters:
" 11 | (mapconcat (lambda (pair) 12 | (format "" 13 | (car pair) (cdr pair))) 14 | (cl-remove-if-not (lambda (el) (stringp (car el))) 15 | headers) 16 | "") 17 | "
%s%s
")))))) 18 | 9004) 19 | -------------------------------------------------------------------------------- /examples/005-post-echo.el: -------------------------------------------------------------------------------- 1 | ;;; post-echo.el --- echo back posted message using Emacs Web Server 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | '(((:POST . ".*") . 6 | (lambda (request) 7 | (with-slots (process headers) request 8 | (let ((message (cdr (assoc "message" headers)))) 9 | (ws-response-header process 200 '("Content-type" . "text/plain")) 10 | (process-send-string process 11 | (if message 12 | (format "you said %S\n" (cdr (assoc 'content message))) 13 | "This is a POST request, but it has no \"message\".\n")))))) 14 | ((:GET . ".*") . 15 | (lambda (request) 16 | (with-slots (process) request 17 | (ws-response-header process 200 '("Content-type" . "text/plain")) 18 | (process-send-string process 19 | "This is a GET request not a POST request.\n"))))) 20 | 9005) 21 | -------------------------------------------------------------------------------- /examples/006-basic-authentication.el: -------------------------------------------------------------------------------- 1 | ;;; basic-authentication.el --- basic authentication 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (lexical-let ((users '(("foo" . "bar") 5 | ("baz" . "qux")))) 6 | (ws-start 7 | (ws-with-authentication 8 | (lambda (request) 9 | (with-slots (process headers) request 10 | (let ((user (caddr (assoc :AUTHORIZATION headers)))) 11 | (ws-response-header process 200 '("Content-type" . "text/plain")) 12 | (process-send-string process (format "welcome %s" user))))) 13 | users) 14 | 9006)) 15 | -------------------------------------------------------------------------------- /examples/007-org-mode-file-server.el: -------------------------------------------------------------------------------- 1 | ;;; org-mode-file-server.el --- serve on-demand exported Org-mode files 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (lexical-let ((docroot "/tmp/")) 5 | (ws-start 6 | (lambda (request) 7 | (with-slots (process headers) request 8 | (let ((path (ws-in-directory-p ; check if path is in docroot 9 | docroot (substring (cdr (assoc :GET headers)) 1)))) 10 | (unless path (ws-send-404 process)) ; send 404 if not in docroot 11 | (if (file-directory-p path) 12 | (progn ;; send directory listing, convert org files to html/tex/txt 13 | (ws-response-header proc 200 (cons "Content-type" "text/html")) 14 | (process-send-string proc 15 | (concat ""))) 32 | ;; Export the file as requested and return the result 33 | (let* ((base (file-name-sans-extension path)) 34 | (type (case (intern (downcase (file-name-extension path))) 35 | (html 'html) 36 | (tex 'latex) 37 | (txt 'ascii) 38 | (t (ws-error process "%S export not supported" 39 | (file-name-extension path))))) 40 | (orig (concat base ".org"))) 41 | (unless (file-exists-p orig) (ws-send-404 process)) 42 | (save-window-excursion (find-file orig) 43 | (org-export-to-file type path)) 44 | (ws-send-file process path)))))) 45 | 9007)) 46 | -------------------------------------------------------------------------------- /examples/008-file-upload.el: -------------------------------------------------------------------------------- 1 | ;;; file-upload.el --- use an uploaded file 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | '(((:POST . ".*") . 6 | (lambda (request) 7 | (with-slots (process headers) request 8 | (ws-response-header process 200 '("Content-type" . "text/plain")) 9 | (let ((file (cdr (assoc "file" headers)))) 10 | (process-send-string process 11 | (concat (sha1 (cdr (assoc 'content file))) " " 12 | (cdr (assoc 'filename file)) "\n"))))))) 13 | 9008) 14 | -------------------------------------------------------------------------------- /examples/009-web-socket.el: -------------------------------------------------------------------------------- 1 | ;;; web-sockets.el --- communicate via web-sockets 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (lexical-let* ((web-socket-port 9009) 5 | (web-socket-page 6 | (format " 7 | 8 | 22 | 23 | 24 |
    25 | 26 |
  1. Press \"connect\" to initialize the web socket connection to 27 | the server. The server will complete the web socket 28 | handshake at which point you'll see an alert with the text 29 | \"connected\".
  2. 30 | 31 |
  3. Press \"message\" to send the string \"foo\" to the server. 32 | The server will reply with the text \"you said: foo\" which 33 | you will see in an alert as \"server: you said: foo\".
  4. 34 | 35 |
  5. Press \"close\" to close the connection. After the server 36 | responds with a close frame you will see an alert with the 37 | text \"connection closed\".
  6. 38 | 39 |
40 |
connect 41 | message 42 | close 43 | 44 | " web-socket-port))) 45 | (ws-start 46 | (lambda (request) 47 | (with-slots (process headers) request 48 | ;; if a web-socket request, then connect and keep open 49 | (if (ws-web-socket-connect request 50 | (lambda (proc string) 51 | (process-send-string proc 52 | (ws-web-socket-frame (concat "you said: " string))))) 53 | (prog1 :keep-alive (setq my-connection process)) 54 | ;; otherwise send the index page 55 | (ws-response-header process 200 '("Content-type" . "text/html")) 56 | (process-send-string process web-socket-page)))) 57 | web-socket-port)) 58 | -------------------------------------------------------------------------------- /examples/010-current-buffer.el: -------------------------------------------------------------------------------- 1 | ;;; current-buffer.el --- Show the current Emacs buffer 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (require 'htmlize) 5 | 6 | (ws-start 7 | (lambda (request) 8 | (with-slots (process headers) request 9 | (ws-response-header process 200 10 | '("Content-type" . "text/html; charset=utf-8")) 11 | (process-send-string process 12 | (let ((html-buffer (htmlize-buffer))) 13 | (prog1 (with-current-buffer html-buffer (buffer-string)) 14 | (kill-buffer html-buffer)))))) 15 | 9010) 16 | -------------------------------------------------------------------------------- /examples/011-org-agenda.el: -------------------------------------------------------------------------------- 1 | ;;; org-agenda.el --- display the Org-mode agenda 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (require 'htmlize) 5 | 6 | (ws-start 7 | (lambda (request) 8 | (with-slots (process headers) request 9 | (ws-response-header process 200 10 | '("Content-type" . "text/html; charset=utf-8")) 11 | (org-agenda nil "a") 12 | (process-send-string process 13 | (save-window-excursion 14 | (let ((html-buffer (htmlize-buffer))) 15 | (prog1 (with-current-buffer html-buffer (buffer-string)) 16 | (kill-buffer html-buffer) 17 | (org-agenda-quit))))))) 18 | 9011) 19 | -------------------------------------------------------------------------------- /examples/012-search-bbdb.el: -------------------------------------------------------------------------------- 1 | ;;; search-bbdb.el --- search the Big Brother Data Base for a supplied name 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (let ((name (cdr (assoc "name" headers)))) 8 | (unless name 9 | (ws-error process "Must specify a name to search.")) 10 | (save-excursion 11 | (unless (set-buffer (get-buffer "*BBDB*")) 12 | (ws-error process "no *BBDB* buffer found")) 13 | (bbdb-search-name name) 14 | (if (equal (point-min) (point-max)) 15 | (progn 16 | (ws-response-header process 404 17 | '("Content-type" . "text/plain")) 18 | (process-send-string process 19 | "no matches found")) 20 | (ws-response-header process 200 21 | '("Content-type" . "text/plain")) 22 | (process-send-string process (buffer-string))))))) 23 | 9012) 24 | -------------------------------------------------------------------------------- /examples/013-org-export-service.el: -------------------------------------------------------------------------------- 1 | ;;; 013-org-export-service.el --- upload and export Org-mode files 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (let ((file (cdr (assoc "file" headers))) 8 | (type (cdr (assoc 'content (cdr (assoc "type" headers)))))) 9 | (if (not (and file type)) 10 | (progn 11 | (ws-response-header process 200 '("Content-type" . "text/html")) 12 | (process-send-string process " 13 |
14 | Export file: to type 15 | 20 | . 21 |
")) 22 | (let* ((orig (cdr (assoc 'filename file))) 23 | (base (file-name-nondirectory 24 | (file-name-sans-extension orig))) 25 | (backend (case (intern (downcase type)) 26 | (html 'html) 27 | (tex 'latex) 28 | (txt 'ascii) 29 | (t (ws-error process "%S export not supported" 30 | type)))) 31 | (path (concat base "." type))) 32 | (let ((default-directory temporary-file-directory)) 33 | (when (or (file-exists-p orig) (file-exists-p path)) 34 | (ws-error process 35 | "File already exists on the server, try a new file.")) 36 | (with-temp-file orig (insert (cdr (assoc 'content file)))) 37 | (save-window-excursion (find-file orig) 38 | ;; TODO: Steal personal data and 39 | ;; ideas from uploaded Org-mode 40 | ;; text. Web services aren't free! 41 | (org-export-to-file backend path) 42 | (kill-buffer)) 43 | (ws-send-file process path) 44 | (delete-file path) 45 | (delete-file orig))))))) 46 | 9013) 47 | -------------------------------------------------------------------------------- /examples/014-org-json.el: -------------------------------------------------------------------------------- 1 | ;;; org-json.el --- Serve Org-mode pages as json 2 | ;; suggested by nicferrier 3 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 4 | 5 | (require 'json) 6 | (lexical-let ((docroot "/tmp/")) 7 | (ws-start 8 | (lambda (request) 9 | (with-slots (process headers) request 10 | (let ((path (ws-in-directory-p 11 | docroot (substring (cdr (assoc :GET headers)) 1)))) 12 | (unless (and path (file-exists-p path)) 13 | (ws-send-404 process)) 14 | (save-window-excursion 15 | (find-file path) 16 | (ws-response-header process 200 17 | '("Content-type" . "application/json")) 18 | (process-send-string process 19 | (let ((tree (org-element-parse-buffer))) 20 | (org-element-map tree 21 | (append org-element-all-objects org-element-all-elements) 22 | (lambda (el) 23 | (org-element-put-property el :parent "none") 24 | (org-element-put-property el :structure "none"))) 25 | (json-encode tree))))))) 26 | 9014)) 27 | -------------------------------------------------------------------------------- /examples/015-auto-mode-server.el: -------------------------------------------------------------------------------- 1 | ;;; auto-mode-server.el --- files with fontification from the `auto-mode-alist' 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (require 'htmlize) 5 | 6 | (lexical-let ((docroot default-directory)) 7 | (ws-start 8 | (lambda (request) 9 | (with-slots (process headers) request 10 | (let ((path (ws-in-directory-p 11 | docroot (substring (cdr (assoc :GET headers)) 1)))) 12 | (if path 13 | (if (file-directory-p path) 14 | (ws-send-directory-list process 15 | (expand-file-name path docroot) "^[^\.]") 16 | ;; send htmlize version of file 17 | (let ((mode (or (cdr (cl-assoc-if (lambda (re) (string-match re path)) 18 | auto-mode-alist)) 19 | 'fundamental-mode))) 20 | (ws-response-header process 200 21 | '("Content-type" . "text/html; charset=utf-8")) 22 | (process-send-string process 23 | (with-temp-buffer 24 | (insert-file-contents-literally path) 25 | (funcall mode) 26 | (let ((html (htmlize-buffer))) 27 | (prog1 (with-current-buffer html (buffer-string)) 28 | (kill-buffer html))))))) 29 | (ws-send-404 process))))) 30 | 9015)) 31 | -------------------------------------------------------------------------------- /examples/016-content-encoding-gzip.el: -------------------------------------------------------------------------------- 1 | ;;; content-encoding-gzip.el -- gzip content encoding 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (with-slots (process headers) request 7 | (ws-response-header process 200 8 | '("Content-type" . "text/plain; charset=utf-8") 9 | '("Content-Encoding" . "x-gzip")) 10 | (let ((s "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec 11 | hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam 12 | nisl, tincidunt et, mattis eget, convallis nec, purus. Cum sociis 13 | natoque penatibus et magnis dis parturient montes, nascetur 14 | ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique 15 | diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam 16 | vestibulum accumsan nisl. 17 | 18 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec 19 | hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam 20 | nisl, tincidunt et, mattis eget, convallis nec, purus. Cum sociis 21 | natoque penatibus et magnis dis parturient montes, nascetur 22 | ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique 23 | diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam 24 | vestibulum accumsan nisl.")) 25 | (ws-send process s)))) 26 | 9016) 27 | -------------------------------------------------------------------------------- /examples/017-transfer-encoding-chunked.el: -------------------------------------------------------------------------------- 1 | ;;; transfer-encoding-chunked.el -- chunked transfer encoding 2 | ;; Copyright (C) 2014 Free Software Foundation, Inc. 3 | 4 | (ws-start 5 | (lambda (request) 6 | (let ((s " 7 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec 8 | hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam 9 | nisl, tincidunt et, mattis eget, convallis nec, purus. Cum sociis 10 | natoque penatibus et magnis dis parturient montes, nascetur 11 | ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique 12 | diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam 13 | vestibulum accumsan nisl. 14 | 15 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec 16 | hendrerit tempor tellus. Donec pretium posuere tellus. Proin quam 17 | nisl, tincidunt et, mattis eget, convallis nec, purus. Cum sociis 18 | natoque penatibus et magnis dis parturient montes, nascetur 19 | ridiculus mus. Nulla posuere. Donec vitae dolor. Nullam tristique 20 | diam non turpis. Cras placerat accumsan nulla. Nullam rutrum. Nam 21 | vestibulum accumsan nisl. 22 | ")) 23 | (with-slots (process headers) request 24 | (ws-response-header process 200 25 | '("Content-type" . "text/plain; charset=utf-8") 26 | '("Transfer-Encoding" . "chunked")) 27 | (ws-send process s) (sit-for 0.5) 28 | (ws-send process s) (sit-for 0.5) 29 | (ws-send process s) (sit-for 0.5) 30 | (ws-send process s)))) 31 | 9017) 32 | -------------------------------------------------------------------------------- /examples/018-web-shell.el: -------------------------------------------------------------------------------- 1 | ;;; web-shell.el --- interact with a SHELL through a web interface 2 | 3 | ;; Copyright (C) 2013-2014 Free Software Foundation, Inc. 4 | 5 | ;; This software is free software: you can redistribute it and/or modify 6 | ;; it under the terms of the GNU General Public License as published by 7 | ;; the Free Software Foundation, either version 3 of the License, or 8 | ;; (at your option) any later version. 9 | 10 | ;; This software is distributed in the hope that it will be useful, 11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ;; GNU General Public License for more details. 14 | 15 | ;; You should have received a copy of the GNU General Public License 16 | ;; along with GNU Emacs. If not, see . 17 | 18 | ;;; Commentary: 19 | 20 | ;; DO NOT RUN THIS EXAMPLE! 21 | 22 | ;; At least not if anyone has network access to your computer. 23 | 24 | ;; This example starts a local shell using the `shell' function. The 25 | ;; resulting comint buffer is then exported using web sockets. 26 | ;; Clients can run local shell commands and see their results through 27 | ;; their browser. 28 | 29 | ;; This example is included because it should be easily generalizable 30 | ;; to build web interfaces to other comint buffers using web sockets. 31 | 32 | ;;; Code: 33 | (defvar web-shell-port 9018) 34 | 35 | (defun web-shell-f-to-s (f) 36 | (with-temp-buffer 37 | (insert-file-contents-literally 38 | (expand-file-name f 39 | (file-name-directory 40 | (or load-file-name buffer-file-name default-directory)))) 41 | (buffer-string))) 42 | 43 | (defvar web-shell-js (web-shell-f-to-s "018-web-shell.js")) 44 | 45 | (defvar web-shell-html (web-shell-f-to-s "018-web-shell.html")) 46 | 47 | (defvar web-shell-socket nil) 48 | 49 | (defun web-shell-socket-respond (string) 50 | (when web-shell-socket 51 | (process-send-string web-shell-socket (ws-web-socket-frame string)))) 52 | 53 | (defun web-shell-socket-handler (process string) 54 | (message "recieved %S" string) 55 | (with-current-buffer "*shell*" 56 | (goto-char (process-mark (get-buffer-process (current-buffer)))) 57 | (insert string) 58 | (comint-send-input))) 59 | 60 | (defun web-shell-handler (request) 61 | (with-slots (process headers) request 62 | ;; if a web-socket request 63 | (if (ws-web-socket-connect request 'web-shell-socket-handler) 64 | ;; then connect and keep open 65 | (prog1 :keep-alive 66 | (setq web-shell-socket process) 67 | (add-hook 'comint-output-filter-functions 'web-shell-socket-respond)) 68 | ;; otherwise send the html and javascript 69 | (save-window-excursion (shell)) 70 | (ws-response-header process 200 '("Content-type" . "text/html")) 71 | (process-send-string process 72 | (format web-shell-html (format web-shell-js web-shell-port)))))) 73 | 74 | (ws-start 'web-shell-handler 9018) 75 | -------------------------------------------------------------------------------- /examples/018-web-shell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 |
 
 9 |   
10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/018-web-shell.js: -------------------------------------------------------------------------------- 1 | var ws; 2 | 3 | function write(data){ 4 | var before = document.getElementById("buffer").innerHTML; 5 | document.getElementById("buffer").innerHTML = before + data; 6 | window.scrollTo(0,document.body.scrollHeight); } 7 | 8 | function read(){ 9 | var tmp = document.getElementById("mini-buffer").value; 10 | document.getElementById("mini-buffer").value = ""; 11 | write(tmp + "\n"); 12 | return tmp; } 13 | 14 | function connect(){ 15 | ws = new WebSocket("ws://localhost:%d/"); 16 | ws.onopen = function() { write("

connected

"); }; 17 | ws.onmessage = function(msg) { write(msg.data); }; 18 | ws.onclose = function() { write("

closed

"); }; } 19 | 20 | window.onload = function(){ 21 | document.getElementById("mini-buffer").addEventListener( 22 | "keyup", function(e){ if(e.keyCode == 13){ ws.send(read()); } }); } 23 | -------------------------------------------------------------------------------- /web-server-status-codes.el: -------------------------------------------------------------------------------- 1 | ;;; web-server-status-codes.el --- Emacs Web Server HTML status codes -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2013-2021 Free Software Foundation, Inc. 4 | 5 | ;; This software is free software: you can redistribute it and/or modify 6 | ;; it under the terms of the GNU General Public License as published by 7 | ;; the Free Software Foundation, either version 3 of the License, or 8 | ;; (at your option) any later version. 9 | 10 | ;; This software is distributed in the hope that it will be useful, 11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ;; GNU General Public License for more details. 14 | 15 | ;; You should have received a copy of the GNU General Public License 16 | ;; along with GNU Emacs. If not, see . 17 | 18 | ;;; Code: 19 | (defvar ws-status-codes 20 | '((100 . "Continue") 21 | (101 . "Switching Protocols") 22 | (102 . "Processing") 23 | (200 . "OK") 24 | (201 . "Created") 25 | (202 . "Accepted") 26 | (203 . "Non-Authoritative Information") 27 | (204 . "No Content") 28 | (205 . "Reset Content") 29 | (206 . "Partial Content") 30 | (207 . "Multi-Status") 31 | (208 . "Already Reported") 32 | (226 . "IM Used") 33 | (300 . "Multiple Choices") 34 | (301 . "Moved Permanently") 35 | (302 . "Found") 36 | (303 . "See Other") 37 | (304 . "Not Modified") 38 | (305 . "Use Proxy") 39 | (306 . "Switch Proxy") 40 | (307 . "Temporary Redirect") 41 | (308 . "Permanent Redirect") 42 | (400 . "Bad Request") 43 | (401 . "Unauthorized") 44 | (402 . "Payment Required") 45 | (403 . "Forbidden") 46 | (404 . "Not Found") 47 | (405 . "Method Not Allowed") 48 | (406 . "Not Acceptable") 49 | (407 . "Proxy Authentication Required") 50 | (408 . "Request Timeout") 51 | (409 . "Conflict") 52 | (410 . "Gone") 53 | (411 . "Length Required") 54 | (412 . "Precondition Failed") 55 | (413 . "Request Entity Too Large") 56 | (414 . "Request-URI Too Long") 57 | (415 . "Unsupported Media Type") 58 | (416 . "Requested Range Not Satisfiable") 59 | (417 . "Expectation Failed") 60 | (418 . "I'm a teapot") 61 | (419 . "Authentication Timeout") 62 | (420 . "Method Failure") 63 | (420 . "Enhance Your Calm") 64 | (422 . "Unprocessable Entity") 65 | (423 . "Locked") 66 | (424 . "Failed Dependency") 67 | (424 . "Method Failure") 68 | (425 . "Unordered Collection") 69 | (426 . "Upgrade Required") 70 | (428 . "Precondition Required") 71 | (429 . "Too Many Requests") 72 | (431 . "Request Header Fields Too Large") 73 | (440 . "Login Timeout") 74 | (444 . "No Response") 75 | (449 . "Retry With") 76 | (450 . "Blocked by Windows Parental Controls") 77 | (451 . "Unavailable For Legal Reasons") 78 | (451 . "Redirect") 79 | (494 . "Request Header Too Large") 80 | (495 . "Cert Error") 81 | (496 . "No Cert") 82 | (497 . "HTTP to HTTPS") 83 | (499 . "Client Closed Request") 84 | (500 . "Internal Server Error") 85 | (501 . "Not Implemented") 86 | (502 . "Bad Gateway") 87 | (503 . "Service Unavailable") 88 | (504 . "Gateway Timeout") 89 | (505 . "HTTP Version Not Supported") 90 | (506 . "Variant Also Negotiates") 91 | (507 . "Insufficient Storage") 92 | (508 . "Loop Detected") 93 | (509 . "Bandwidth Limit Exceeded") 94 | (510 . "Not Extended") 95 | (511 . "Network Authentication Required") 96 | (520 . "Origin Error") 97 | (522 . "Connection timed out") 98 | (523 . "Proxy Declined Request") 99 | (524 . "A timeout occurred") 100 | (598 . "Network read timeout error") 101 | (599 . "Network connect timeout error")) 102 | "Possible HTML status codes with names. 103 | From http://en.wikipedia.org/wiki/List_of_HTTP_status_codes.") 104 | 105 | (provide 'web-server-status-codes) 106 | ;;; web-server-status-codes.el ends here 107 | -------------------------------------------------------------------------------- /web-server-test.el: -------------------------------------------------------------------------------- 1 | ;;; web-server-test.el --- Test the Emacs Web Server -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2013-2021 Free Software Foundation, Inc. 4 | 5 | ;; Author: Eric Schulte 6 | 7 | ;; This software is free software: you can redistribute it and/or modify 8 | ;; it under the terms of the GNU General Public License as published by 9 | ;; the Free Software Foundation, either version 3 of the License, or 10 | ;; (at your option) any later version. 11 | 12 | ;; This software is distributed in the hope that it will be useful, 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | ;; GNU General Public License for more details. 16 | 17 | ;; You should have received a copy of the GNU General Public License 18 | ;; along with GNU Emacs. If not, see . 19 | 20 | ;;; Code: 21 | (require 'web-server) 22 | (require 'cl-lib) 23 | (require 'ert) 24 | 25 | (defvar ws-test-port 8999) 26 | 27 | (defun ws-test-curl-to-string (url &optional get-params post-params curl-flags) 28 | "Curl URL with optional parameters." 29 | (async-shell-command 30 | (format "curl -s -m 4 %s %s %s localhost:%s/%s" 31 | (or curl-flags "") 32 | (if get-params 33 | (mapconcat (lambda (p) (format "-d \"%s=%s\"" (car p) (cdr p))) 34 | get-params " ") 35 | "") 36 | (if post-params 37 | (mapconcat (lambda (p) (format "-F \"%s=%s\"" (car p) (cdr p))) 38 | post-params " ") 39 | "") 40 | ws-test-port url)) 41 | (unwind-protect 42 | (with-current-buffer "*Async Shell Command*" 43 | (while (get-buffer-process (current-buffer)) (sit-for 0.1)) 44 | (goto-char (point-min)) 45 | (buffer-string)) 46 | (kill-buffer "*Async Shell Command*"))) 47 | 48 | (defmacro ws-test-with (handler &rest body) 49 | (declare (indent 1)) 50 | (let ((srv (cl-gensym))) 51 | `(let* ((,srv (ws-start ,handler ws-test-port))) 52 | (unwind-protect (progn ,@body) (ws-stop ,srv))))) 53 | (def-edebug-spec ws-test-with (form body)) 54 | 55 | (ert-deftest ws/keyword-style-handler () 56 | "Ensure that a simple keyword-style handler matches correctly." 57 | (ws-test-with (mapcar (lambda (letter) 58 | `((:GET . ,letter) . 59 | (lambda (request) 60 | (ws-response-header (ws-process request) 200 61 | '("Content-type" . "text/plain")) 62 | (process-send-string (ws-process request) 63 | (concat "returned:" ,letter))))) 64 | '("a" "b")) 65 | (should (string= "returned:a" (ws-test-curl-to-string "a"))) 66 | (should (string= "returned:b" (ws-test-curl-to-string "b"))))) 67 | 68 | (ert-deftest ws/function-style-handler () 69 | "Test that a simple hello-world server responds." 70 | (ws-test-with 71 | '(((lambda (_) t) . 72 | (lambda (request) 73 | (ws-response-header (ws-process request) 200 74 | '("Content-type" . "text/plain")) 75 | (process-send-string (ws-process request) "hello world")))) 76 | (should (string= (ws-test-curl-to-string "") "hello world")))) 77 | 78 | (ert-deftest ws/removed-from-ws-servers-after-stop () 79 | (let ((start-length (length ws-servers))) 80 | (let ((server (ws-start nil ws-test-port))) 81 | (should (= (length ws-servers) (+ 1 start-length))) 82 | (ws-stop server) 83 | (should (= (length ws-servers) start-length))))) 84 | 85 | (ert-deftest ws/parse-many-headers () 86 | "Test that a number of headers parse successfully." 87 | (let ((server (ws-start nil ws-test-port)) 88 | (request (make-instance 'ws-request))) 89 | (unwind-protect 90 | (progn 91 | (setf (ws-pending request) 92 | "GET / HTTP/1.1 93 | Host: localhost:7777 94 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 95 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 96 | Accept-Language: en-US,en;q=0.5 97 | Accept-Encoding: gzip, deflate 98 | DNT: 1 99 | Cookie: __utma=111872281.1462392269.1345929539.1345929539.1345929539.1 100 | Connection: keep-alive 101 | 102 | ") 103 | (ws-parse-request request) 104 | (let ((headers (cdr (ws-headers request)))) 105 | (should (string= (cdr (assoc :ACCEPT-ENCODING headers)) 106 | "gzip, deflate")) 107 | (should (string= (cdr (assoc :GET headers)) "/")) 108 | (should (string= (cdr (assoc :CONNECTION headers)) "keep-alive")))) 109 | (ws-stop server)))) 110 | 111 | (ert-deftest ws/parse-post-data () 112 | (let ((server (ws-start nil ws-test-port)) 113 | (request (make-instance 'ws-request))) 114 | (unwind-protect 115 | (progn 116 | (setf (ws-pending request) 117 | "POST / HTTP/1.1 118 | User-Agent: curl/7.33.0 119 | Host: localhost:8080 120 | Accept: */* 121 | Content-Length: 273 122 | Expect: 100-continue 123 | Content-Type: multipart/form-data; boundary=----------------f1270d0deb77af03 124 | 125 | ------------------f1270d0deb77af03 126 | Content-Disposition: form-data; name=\"date\" 127 | 128 | Wed Dec 18 00:55:39 MST 2013 129 | 130 | ------------------f1270d0deb77af03 131 | Content-Disposition: form-data; name=\"name\" 132 | 133 | \"schulte\" 134 | ------------------f1270d0deb77af03-- 135 | ") 136 | (ws-parse-request request) 137 | (let ((headers (cdr (ws-headers request)))) 138 | (should (string= (cdr (assoc 'content (cdr (assoc "name" headers)))) 139 | "\"schulte\"")) 140 | (should (string= (cdr (assoc 'content (cdr (assoc "date" headers)))) 141 | "Wed Dec 18 00:55:39 MST 2013\n")))) 142 | (ws-stop server)))) 143 | 144 | (ert-deftest ws/parse-another-post-data () 145 | "This one from an AJAX request." 146 | (let ((server (ws-start nil ws-test-port)) 147 | (request (make-instance 'ws-request))) 148 | (unwind-protect 149 | (progn 150 | (setf (ws-pending request) 151 | "POST /complex.org HTTP/1.1 152 | Host: localhost:4444 153 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 154 | Accept: */* 155 | Accept-Language: en-US,en;q=0.5 156 | Accept-Encoding: gzip, deflate 157 | DNT: 1 158 | Content-Type: application/x-www-form-urlencoded; charset=UTF-8 159 | X-Requested-With: XMLHttpRequest 160 | Referer: http://localhost:4444/complex.org 161 | Content-Length: 78 162 | Cookie: __utma=111872281.1462392269.1345929539.1345929539.1345929539.1 163 | Connection: keep-alive 164 | Pragma: no-cache 165 | Cache-Control: no-cache 166 | 167 | org=-+one%0A-+two%0A-+three%0A-+four%0A%0A&beg=646&end=667&path=%2Fcomplex.org") 168 | (ws-parse-request request) 169 | (let ((headers (cdr (ws-headers request)))) 170 | (should (string= (cdr (assoc "path" headers)) "/complex.org")) 171 | (should (string= (cdr (assoc "beg" headers)) "646")) 172 | (should (string= (cdr (assoc "end" headers)) "667")) 173 | (should (string= (cdr (assoc "org" headers)) 174 | "- one 175 | - two 176 | - three 177 | - four 178 | 179 | ")) 180 | (should (string= (cdr (assoc :CONTENT-TYPE headers)) 181 | "application/x-www-form-urlencoded; charset=UTF-8")) 182 | (should (string= (oref request body) 183 | "org=-+one%0A-+two%0A-+three%0A-+four%0A%0A&beg=646&end=667&path=%2Fcomplex.org")))) 184 | (ws-stop server)))) 185 | 186 | (ert-deftest ws/parse-json-data () 187 | "Ensure we can send arbitrary data through to the handler 188 | 189 | The handler can then parse it itself." 190 | (let ((server (ws-start nil ws-test-port)) 191 | (request (make-instance 'ws-request))) 192 | (unwind-protect 193 | (progn 194 | (setf (ws-pending request) 195 | "POST /complex.org HTTP/1.1 196 | Host: localhost:4444 197 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:26.0) Gecko/20100101 Firefox/26.0 198 | Accept: */* 199 | Accept-Language: en-US,en;q=0.5 200 | Accept-Encoding: gzip, deflate 201 | DNT: 1 202 | Content-Type: application/json 203 | Referer: http://localhost:4444/complex.org 204 | Content-Length: 33 205 | Cookie: __utma=111872281.1462392269.1345929539.1345929539.1345929539.1 206 | Connection: keep-alive 207 | Pragma: no-cache 208 | Cache-Control: no-cache 209 | 210 | {\"some example\": \"json data\"}") 211 | (ws-parse-request request) 212 | (let ((headers (cdr (ws-headers request)))) 213 | (should (string= (cdr (assoc :CONTENT-TYPE headers)) 214 | "application/json")) 215 | (should (string= (oref request body) 216 | "{\"some example\": \"json data\"}"))) 217 | (ws-stop server))))) 218 | 219 | (ert-deftest ws/simple-post () 220 | "Test a simple POST server." 221 | (ws-test-with 222 | '(((:POST . ".*") . 223 | (lambda (request) 224 | (with-slots (process headers) request 225 | (let ((message (cdr (assoc "message" headers)))) 226 | (ws-response-header process 200 227 | '("Content-type" . "text/plain")) 228 | (process-send-string process 229 | (format "you said %S\n" (cdr (assoc 'content message))))))))) 230 | (should (string= (ws-test-curl-to-string "" nil '(("message" . "foo"))) 231 | "you said \"foo\"\n")))) 232 | 233 | (ert-deftest ws/in-directory-p () 234 | (mapc (lambda (pair) 235 | (let ((should-or-not (car pair)) 236 | (dir (cdr pair))) 237 | (message "dir: %S" dir) 238 | (should 239 | (funcall (if should-or-not #'identity #'not) 240 | (ws-in-directory-p temporary-file-directory dir))))) 241 | `((nil . "foo/bar/../../../") 242 | (t . ,(concat 243 | "foo/bar/../../../" 244 | (file-name-nondirectory 245 | (directory-file-name temporary-file-directory)) 246 | "/baz")) 247 | (t . "./") 248 | (nil . "/~/pics") 249 | (nil . "~/pics") 250 | (nil . "/pics") 251 | (nil . "../pics") 252 | (t . "pics") 253 | (nil . "..")))) 254 | 255 | (ert-deftest ws/parse-basic-authorization () 256 | "Test that a number of headers parse successfully." 257 | (let* ((server (ws-start nil ws-test-port)) 258 | (request (make-instance 'ws-request)) 259 | (username "foo") (password "bar")) 260 | (unwind-protect 261 | (progn 262 | (setf (ws-pending request) 263 | (format "GET / HTTP/1.1 264 | Authorization: Basic %s 265 | Connection: keep-alive 266 | 267 | " (base64-encode-string (concat username ":" password)))) 268 | (ws-parse-request request) 269 | (with-slots (headers) request 270 | (cl-tree-equal (cdr (assoc :AUTHORIZATION headers)) 271 | (cons :BASIC (cons username password))))) 272 | (ws-stop server)))) 273 | 274 | (ert-deftest ws/parse-large-file-upload () 275 | "Test that `ws-parse-request' can handle at large file upload. 276 | At least when it comes in a single chunk." 277 | (let* ((long-string (mapconcat #'int-to-string (number-sequence 0 20000) " ")) 278 | (server (ws-start nil ws-test-port)) 279 | (request (make-instance 'ws-request))) 280 | (unwind-protect 281 | (progn 282 | (setf (ws-pending request) 283 | (format "POST / HTTP/1.1 284 | User-Agent: curl/7.34.0 285 | Host: localhost:9008 286 | Accept: */* 287 | Content-Length: 9086 288 | Expect: 100-continue 289 | Content-Type: multipart/form-data; boundary=----------------e458fb665704290b 290 | 291 | ------------------e458fb665704290b 292 | Content-Disposition: form-data; name=\"file\"; filename=\"-\" 293 | Content-Type: application/octet-stream 294 | 295 | %s 296 | ------------------e458fb665704290b-- 297 | 298 | " long-string)) 299 | (ws-parse-request request) 300 | (should 301 | (string= long-string 302 | (cdr (assoc 'content 303 | (cdr (assoc "file" (ws-headers request)))))))) 304 | (ws-stop server)))) 305 | 306 | (ert-deftest ws/web-socket-handshake-rfc-example () 307 | "Ensure that `ws-web-socket-handshake' conforms to the example in RFC6455." 308 | (should (string= (ws-web-socket-handshake "dGhlIHNhbXBsZSBub25jZQ==") 309 | "s3pPLMBiTxaQ9kYGzzhZRbK+xOo="))) 310 | 311 | (ert-deftest ws/web-socket-frame () 312 | "Test WebSocket frame encoding for the different varint payload lengths: 313 | 0-125, 126-64k, 64k-2^64." 314 | (should (string= (ws-web-socket-frame "short") "\201short")) 315 | (should (string= (substring (ws-web-socket-frame (make-string 126 ?a)) 316 | 0 5) "\201~\0~a")) 317 | (should (string= (substring (ws-web-socket-frame (make-string 65536 ?a)) 318 | 0 11) "\201\0\0\0\0\0\0\0a"))) 319 | 320 | (ert-deftest ws/simple-chunked () 321 | "Test a simple server using chunked transfer encoding." 322 | (ws-test-with 323 | (lambda (request) 324 | (with-slots (process) request 325 | (ws-response-header process 200 326 | '("Content-type" . "text/plain") 327 | '("Transfer-Encoding" . "chunked")) 328 | (ws-send process "I am chunked"))) 329 | (should (string= (ws-test-curl-to-string "") "I am chunked")))) 330 | 331 | (ert-deftest ws/simple-gzip () 332 | "Test a simple server using gzip content/transfer encoding." 333 | (cl-macrolet ((gzipper (header) 334 | `(ws-test-with 335 | (lambda (request) 336 | (with-slots (process) request 337 | (ws-response-header process 200 338 | '("Content-type" . "text/plain") 339 | '(,header . "gzip")) 340 | (ws-send process "I am zipped"))) 341 | (should (string= (ws-test-curl-to-string 342 | "" nil nil "--compressed") 343 | "I am zipped"))))) 344 | (gzipper "Content-Encoding") 345 | (gzipper "Transfer-Encoding"))) 346 | 347 | (provide 'web-server-test) 348 | -------------------------------------------------------------------------------- /web-server.el: -------------------------------------------------------------------------------- 1 | ;;; web-server.el --- Emacs Web Server -*- lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2013-2014 Free Software Foundation, Inc. 4 | 5 | ;; Author: Eric Schulte 6 | ;; Maintainer: Eric Schulte 7 | ;; Version: 0.1.2 8 | ;; Package-Requires: ((emacs "24.1") (cl-lib "0.6")) 9 | ;; Keywords: http, server, network 10 | ;; URL: https://github.com/eschulte/emacs-web-server 11 | 12 | ;; This software is free software: you can redistribute it and/or modify 13 | ;; it under the terms of the GNU General Public License as published by 14 | ;; the Free Software Foundation, either version 3 of the License, or 15 | ;; (at your option) any later version. 16 | 17 | ;; This software is distributed in the hope that it will be useful, 18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | ;; GNU General Public License for more details. 21 | 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with GNU Emacs. If not, see . 24 | 25 | ;;; Commentary: 26 | 27 | ;; A web server in Emacs running handlers written in Emacs Lisp. 28 | ;; 29 | ;; Full support for GET and POST requests including URL-encoded 30 | ;; parameters and multipart/form data. Supports web sockets. 31 | ;; 32 | ;; See the examples/ directory for examples demonstrating the usage of 33 | ;; the Emacs Web Server. The following launches a simple "hello 34 | ;; world" server. 35 | ;; 36 | ;; (ws-start 37 | ;; '(((lambda (_) t) . ; match every request 38 | ;; (lambda (request) ; reply with "hello world" 39 | ;; (with-slots (process) request 40 | ;; (ws-response-header process 200 '("Content-type" . "text/plain")) 41 | ;; (process-send-string process "hello world"))))) 42 | ;; 9000) 43 | 44 | ;;; Code: 45 | (require 'web-server-status-codes) 46 | (require 'mail-parse) ; to parse multipart data in headers 47 | (require 'mm-encode) ; to look-up mime types for files 48 | (require 'url-util) ; to decode url-encoded params 49 | (require 'eieio) 50 | (require 'cl-lib) 51 | 52 | (defclass ws-server () 53 | ((handlers :initarg :handlers :accessor ws-handlers :initform nil) 54 | (process :initarg :process :accessor ws-process :initform nil) 55 | (port :initarg :port :accessor ws-port :initform nil) 56 | (requests :initarg :requests :accessor ws-requests :initform nil))) 57 | 58 | (defclass ws-request () 59 | ((process :initarg :process :accessor ws-process :initform nil) 60 | (pending :initarg :pending :accessor ws-pending :initform "") 61 | (context :initarg :context :accessor ws-context :initform nil) 62 | (boundary :initarg :boundary :accessor ws-boundary :initform nil) 63 | (index :initarg :index :accessor ws-index :initform 0) 64 | (active :initarg :active :accessor ws-active :initform nil) 65 | (headers :initarg :headers :accessor ws-headers :initform (list nil)) 66 | (body :initarg :body :accessor ws-body :initform ""))) 67 | 68 | (defvar ws-servers nil 69 | "List holding all web servers.") 70 | 71 | (defvar ws-log-time-format "%Y.%m.%d.%H.%M.%S.%N" 72 | "Logging time format passed to `format-time-string'.") 73 | 74 | (defvar ws-guid "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 75 | "This GUID is defined in RFC6455.") 76 | 77 | ;;;###autoload 78 | (defun ws-start (handlers port &optional log-buffer &rest network-args) 79 | "Start a server using HANDLERS and return the server object. 80 | 81 | HANDLERS may be a single function (which is then called on every 82 | request) or a list of conses of the form (MATCHER . FUNCTION), 83 | where the FUNCTION associated with the first successful MATCHER 84 | is called. Handler functions are called with two arguments, the 85 | process and the request object. 86 | 87 | A MATCHER may be either a function (in which case it is called on 88 | the request object) or a cons cell of the form (KEYWORD . STRING) 89 | in which case STRING is matched against the value of the header 90 | specified by KEYWORD. 91 | 92 | Any supplied NETWORK-ARGS are assumed to be keyword arguments for 93 | `make-network-process' to which they are passed directly. 94 | 95 | For example, the following starts a simple hello-world server on 96 | port 8080. 97 | 98 | (ws-start 99 | (lambda (request) 100 | (with-slots (process headers) request 101 | (process-send-string process 102 | \"HTTP/1.1 200 OK\\r\\nContent-Type: text/plain\\r\\n\\r\\nhello world\"))) 103 | 8080) 104 | 105 | Equivalently, the following starts an identical server using a 106 | function MATCH and the `ws-response-header' convenience 107 | function. 108 | 109 | (ws-start 110 | `(((lambda (_) t) . 111 | (lambda (request) 112 | (with-slots ((proc process)) request 113 | (ws-response-header proc 200 '(\"Content-Type\" . \"text/plain\")) 114 | (process-send-string proc \"hello world\"))))) 115 | 8080) 116 | 117 | " 118 | (let ((server (make-instance 'ws-server :handlers handlers :port port)) 119 | (log (when log-buffer (get-buffer-create log-buffer)))) 120 | (setf (ws-process server) 121 | (apply 122 | #'make-network-process 123 | :name "ws-server" 124 | :service (ws-port server) 125 | :filter 'ws-filter 126 | :server t 127 | :nowait (< emacs-major-version 26) 128 | :family 'ipv4 129 | :coding 'no-conversion 130 | :plist (append (list :server server) 131 | (when log (list :log-buffer log))) 132 | :log (when log 133 | (lambda (proc request message) 134 | (let ((c (process-contact request)) 135 | (buf (plist-get (process-plist proc) :log-buffer))) 136 | (with-current-buffer buf 137 | (goto-char (point-max)) 138 | (insert (format "%s\t%s\t%s\t%s" 139 | (format-time-string ws-log-time-format) 140 | (cl-first c) (cl-second c) message)))))) 141 | network-args)) 142 | (push server ws-servers) 143 | server)) 144 | 145 | (defun ws-stop (server) 146 | "Stop SERVER." 147 | (setq ws-servers (remove server ws-servers)) 148 | (mapc #'delete-process (append (mapcar #'ws-process (ws-requests server)) 149 | (list (ws-process server))))) 150 | 151 | (defun ws-stop-all () 152 | "Stop all servers in `ws-servers'." 153 | (interactive) 154 | (mapc #'ws-stop ws-servers)) 155 | 156 | (defvar ws-http-common-methods '(GET HEAD POST PUT DELETE TRACE) 157 | "HTTP methods from http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html.") 158 | 159 | (defvar ws-http-method-rx 160 | (format "^\\(%s\\) \\([^[:space:]]+\\) \\([^[:space:]]+\\)$" 161 | (mapconcat #'symbol-name ws-http-common-methods "\\|"))) 162 | 163 | (defun ws-parse-query-string (string) 164 | "Thin wrapper around `url-parse-query-string'." 165 | (mapcar (lambda (pair) (cons (cl-first pair) (cl-second pair))) 166 | (url-parse-query-string string nil 'allow-newlines))) 167 | 168 | (defun ws-parse (proc string) 169 | "Parse HTTP headers in STRING reporting errors to PROC." 170 | (cl-flet ((to-keyword (s) (intern (concat ":" (upcase s))))) 171 | (cond 172 | ;; Method 173 | ((string-match ws-http-method-rx string) 174 | (let ((method (to-keyword (match-string 1 string))) 175 | (url (match-string 2 string))) 176 | (if (string-match "?" url) 177 | (cons (cons method (substring url 0 (match-beginning 0))) 178 | (ws-parse-query-string 179 | (url-unhex-string (substring url (match-end 0))))) 180 | (list (cons method url))))) 181 | ;; Authorization 182 | ((string-match "^AUTHORIZATION: \\([^[:space:]]+\\) \\(.*\\)$" string) 183 | (let ((protocol (to-keyword (match-string 1 string))) 184 | (credentials (match-string 2 string))) 185 | (list (cons :AUTHORIZATION 186 | (cons protocol 187 | (cl-case protocol 188 | (:BASIC 189 | (let ((cred (base64-decode-string credentials))) 190 | (if (string-match ":" cred) 191 | (cons (substring cred 0 (match-beginning 0)) 192 | (substring cred (match-end 0))) 193 | (ws-error proc "bad credentials: %S" cred)))) 194 | (t (ws-error proc "un-support protocol: %s" 195 | protocol)))))))) 196 | ;; All other headers 197 | ((string-match "^\\([^[:space:]]+\\): \\(.*\\)$" string) 198 | (list (cons (to-keyword (match-string 1 string)) 199 | (match-string 2 string)))) 200 | (:otherwise (ws-error proc "bad header: %S" string) nil)))) 201 | 202 | (defun ws-trim (string) 203 | (while (and (> (length string) 0) 204 | (or (and (string-match "[\r\n]" (substring string -1)) 205 | (setq string (substring string 0 -1))) 206 | (and (string-match "[\r\n]" (substring string 0 1)) 207 | (setq string (substring string 1)))))) 208 | string) 209 | 210 | (defun ws-parse-multipart/form (proc string) 211 | ;; ignore empty and non-content blocks 212 | (when (string-match "Content-Disposition:[[:space:]]*\\(.*\\)\r\n" string) 213 | (let ((dp (cdr (mail-header-parse-content-disposition 214 | (match-string 1 string)))) 215 | (last-index (match-end 0)) 216 | index) 217 | ;; every line up until the double \r\n is a header 218 | (while (and (setq index (string-match "\r\n" string last-index)) 219 | (not (= index last-index))) 220 | (setcdr (last dp) (ws-parse proc (substring string last-index index))) 221 | (setq last-index (+ 2 index))) 222 | ;; after double \r\n is all content 223 | (cons (cdr (assoc 'name dp)) 224 | (cons (cons 'content (substring string (+ 2 last-index))) 225 | dp))))) 226 | 227 | (defun ws-filter (proc string) 228 | (with-slots (handlers requests) (plist-get (process-plist proc) :server) 229 | (unless (cl-find-if (lambda (c) (equal proc (ws-process c))) requests) 230 | (push (make-instance 'ws-request :process proc) requests)) 231 | (let ((request (cl-find-if (lambda (c) (equal proc (ws-process c))) requests))) 232 | (with-slots (pending) request (setq pending (concat pending string))) 233 | (unless (ws-active request) ; don't re-start if request is being parsed 234 | (setf (ws-active request) t) 235 | (when (not (eq (catch 'close-connection 236 | (if (ws-parse-request request) 237 | (ws-call-handler request handlers) 238 | :keep-alive)) 239 | :keep-alive)) 240 | ;; Properly shut down processes requiring an ending (e.g., chunked) 241 | (let ((ender (plist-get (process-plist proc) :ender))) 242 | (when ender (process-send-string proc ender))) 243 | (setq requests (cl-remove-if (lambda (r) (eql proc (ws-process r))) requests)) 244 | (delete-process proc)))))) 245 | 246 | (defun ws-parse-request (request) 247 | "Parse request STRING from REQUEST with process PROC. 248 | Return non-nil only when parsing is complete." 249 | (catch 'finished-parsing-headers 250 | (with-slots (process pending context boundary headers body index) request 251 | (let ((delimiter (concat "\r\n" (if boundary (concat "--" boundary) ""))) 252 | ;; Track progress through string, always work with the 253 | ;; section of string between INDEX and NEXT-INDEX. 254 | next-index 255 | body-stored) 256 | ;; parse headers and append to request 257 | (while (setq next-index (string-match delimiter pending index)) 258 | (let ((tmp (+ next-index (length delimiter)))) 259 | (if (= index next-index) ; double \r\n ends current run of headers 260 | (progn 261 | ;; Store the body 262 | (unless 263 | ;; Multipart form data has multiple passes - store on 264 | ;; first pass only. 265 | body-stored 266 | (let ((after-headers (substring pending index))) 267 | (when (string-prefix-p "\r\n" after-headers) 268 | (setq body 269 | ;; Trim off the additional CRLF 270 | (substring after-headers 2)))) 271 | (setq body-stored t)) 272 | (cl-case context 273 | ;; Parse URL data. 274 | ;; http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 275 | (application/x-www-form-urlencoded 276 | (mapc (lambda (pair) (setcdr (last headers) (list pair))) 277 | (ws-parse-query-string 278 | (replace-regexp-in-string 279 | "\\+" " " 280 | (ws-trim (substring pending index))))) 281 | (throw 'finished-parsing-headers t)) 282 | ;; Set custom delimiter for multipart form data. 283 | (multipart/form-data 284 | (setq delimiter (concat "\r\n--" boundary))) 285 | ;; No special context so we're done. 286 | (t (throw 'finished-parsing-headers t)))) 287 | (if (eql context 'multipart/form-data) 288 | (progn 289 | (setcdr (last headers) 290 | (list (ws-parse-multipart/form process 291 | (substring pending index next-index)))) 292 | ;; Boundary suffixed by "--" indicates end of the headers. 293 | (when (and (> (length pending) (+ tmp 2)) 294 | (string= (substring pending tmp (+ tmp 2)) "--")) 295 | (throw 'finished-parsing-headers t))) 296 | ;; Standard header parsing. 297 | (let ((header (ws-parse process (substring pending 298 | index next-index)))) 299 | ;; Content-Type indicates that the next double \r\n 300 | ;; will be followed by a special type of content which 301 | ;; will require special parsing. Thus we will note 302 | ;; the type in the CONTEXT variable for parsing 303 | ;; dispatch above. 304 | (when (and (caar header) (eql (caar header) :CONTENT-TYPE)) 305 | (cl-destructuring-bind (type &rest data) 306 | (mail-header-parse-content-type (cdar header)) 307 | (setq boundary (cdr (assoc 'boundary data))) 308 | (setq context (intern (downcase type))))) 309 | ;; All other headers are collected directly. 310 | (setcdr (last headers) header)))) 311 | (setq index tmp))))) 312 | (setf (ws-active request) nil) 313 | nil)) 314 | 315 | (defun ws-call-handler (request handlers) 316 | (catch 'matched-handler 317 | (when (functionp handlers) 318 | (throw 'matched-handler 319 | (condition-case e (funcall handlers request) 320 | (error (ws-error (ws-process request) "Caught Error: %S" e))))) 321 | (mapc (lambda (handler) 322 | (let ((match (car handler)) 323 | (function (cdr handler))) 324 | (when (or (and (consp match) 325 | (assoc (car match) (ws-headers request)) 326 | (string-match (cdr match) 327 | (cdr (assoc (car match) 328 | (ws-headers request))))) 329 | (and (functionp match) (funcall match request))) 330 | (throw 'matched-handler 331 | (condition-case e (funcall function request) 332 | (error (ws-error (ws-process request) 333 | "Caught Error: %S" e))))))) 334 | handlers) 335 | (ws-error (ws-process request) "no handler matched request: %S" 336 | (ws-headers request)))) 337 | 338 | (defun ws-error (proc msg &rest args) 339 | (let ((buf (plist-get (process-plist proc) :log-buffer)) 340 | (c (process-contact proc))) 341 | (when buf 342 | (with-current-buffer buf 343 | (goto-char (point-max)) 344 | (insert (format "%s\t%s\t%s\tWS-ERROR: %s" 345 | (format-time-string ws-log-time-format) 346 | (cl-first c) (cl-second c) 347 | (apply #'format msg args))))) 348 | (apply #'ws-send-500 proc msg args))) 349 | 350 | 351 | ;;; Web Socket 352 | ;; Implement to conform to http://tools.ietf.org/html/rfc6455. 353 | 354 | ;; The `ws-message' object is used to hold state across multiple calls 355 | ;; of the process filter on the websocket network process. The fields 356 | ;; play the following roles. 357 | ;; process ------ holds the process itself, used for communication 358 | ;; pending ------ holds text received from the client but not yet parsed 359 | ;; active ------- indicates that parsing is active to avoid re-entry 360 | ;; of the `ws-web-socket-parse-messages' function 361 | ;; new ---------- indicates that new text was received during parsing 362 | ;; and causes `ws-web-socket-parse-messages' to be 363 | ;; called again after it terminates 364 | ;; data --------- holds the data of parsed messages 365 | ;; handler ------ holds the user-supplied function of two arguments 366 | ;; called on the process and the data of parsed 367 | ;; messages 368 | (defclass ws-message () ; web socket message object 369 | ((process :initarg :process :accessor ws-process :initform "") 370 | (pending :initarg :pending :accessor ws-pending :initform "") 371 | (active :initarg :active :accessor ws-active :initform nil) 372 | (new :initarg :new :accessor ws-new :initform nil) 373 | (data :initarg :data :accessor ws-data :initform "") 374 | (handler :initarg :handler :accessor ws-handler :initform ""))) 375 | 376 | (defun ws-web-socket-connect (request handler) 377 | "Establish a web socket connection with request. 378 | If the connection is successful this function will throw 379 | `:keep-alive' to `close-connection' skipping any remaining code 380 | in the request handler. If no web-socket connection is 381 | established (e.g., because REQUEST is not attempting to establish 382 | a connection) then no actions are taken and nil is returned. 383 | 384 | Second argument HANDLER should be a function of two arguments, 385 | the process and a string, which will be called on all complete 386 | messages as they are received and parsed from the network." 387 | (with-slots (process headers) request 388 | (when (assoc :SEC-WEBSOCKET-KEY headers) 389 | ;; Accept the connection 390 | (ws-response-header process 101 391 | (cons "Upgrade" "websocket") 392 | (cons "Connection" "upgrade") 393 | (cons "Sec-WebSocket-Accept" 394 | (ws-web-socket-handshake 395 | (cdr (assoc :SEC-WEBSOCKET-KEY headers))))) 396 | ;; Setup the process filter 397 | (set-process-coding-system process 'binary) 398 | (set-process-plist 399 | process (list :message (make-instance 'ws-message 400 | :handler handler :process process))) 401 | (set-process-filter process 'ws-web-socket-filter) 402 | process))) 403 | 404 | (defun ws-web-socket-filter (process string) 405 | (let ((message (plist-get (process-plist process) :message))) 406 | (if (ws-active message) ; don't re-start if message is being parsed 407 | (setf (ws-new message) string) 408 | (setf (ws-pending message) (concat (ws-pending message) string)) 409 | (setf (ws-active message) t) 410 | (ws-web-socket-parse-messages message)) 411 | (setf (ws-active message) nil))) 412 | 413 | (defun ws-web-socket-mask (masking-key data) 414 | (let ((masking-data (apply #'concat (make-list (+ 1 (/ (length data) 4)) 415 | masking-key)))) 416 | (apply #'string (cl-mapcar #'logxor masking-data data)))) 417 | 418 | ;; Binary framing protocol 419 | ;; from http://tools.ietf.org/html/rfc6455#section-5.2 420 | ;; 421 | ;; 0 1 2 3 422 | ;; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 423 | ;; +-+-+-+-+-------+-+-------------+-------------------------------+ 424 | ;; |F|R|R|R| opcode|M| Payload len | Extended payload length | 425 | ;; |I|S|S|S| (4) |A| (7) | (16/64) | 426 | ;; |N|V|V|V| |S| | (if payload len==126/127) | 427 | ;; | |1|2|3| |K| | | 428 | ;; +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + 429 | ;; | Extended payload length continued, if payload len == 127 | 430 | ;; + - - - - - - - - - - - - - - - +-------------------------------+ 431 | ;; | |Masking-key, if MASK set to 1 | 432 | ;; +-------------------------------+-------------------------------+ 433 | ;; | Masking-key (continued) | Payload Data | 434 | ;; +-------------------------------- - - - - - - - - - - - - - - - + 435 | ;; : Payload Data continued ... : 436 | ;; + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 437 | ;; | Payload Data continued ... | 438 | ;; +---------------------------------------------------------------+ 439 | ;; 440 | (defun ws-web-socket-parse-messages (message) 441 | "Web socket filter to pass whole frames to the client. 442 | See RFC6455." 443 | (with-slots (process active pending data handler new) message 444 | (let ((index 0)) 445 | (cl-labels ((int-to-bits (int size) 446 | (let ((result (make-bool-vector size nil))) 447 | (mapc (lambda (place) 448 | (let ((val (expt 2 place))) 449 | (when (>= int val) 450 | (setq int (- int val)) 451 | (aset result place t)))) 452 | (reverse (number-sequence 0 (- size 1)))) 453 | (reverse (append result nil)))) 454 | (bits-to-int (bits) 455 | (let ((place 0)) 456 | (apply #'+ 457 | (mapcar (lambda (bit) 458 | (prog1 (if bit (expt 2 place) 0) (cl-incf place))) 459 | (reverse bits))))) 460 | (bits (length) 461 | (apply #'append 462 | (mapcar (lambda (int) (int-to-bits int 8)) 463 | (cl-subseq 464 | pending index (cl-incf index length)))))) 465 | (let (fin rsvs opcode mask pl mask-key) 466 | ;; Parse fin bit, rsvs bits and opcode 467 | (let ((byte (bits 1))) 468 | (setq fin (car byte) 469 | rsvs (cl-subseq byte 1 4) 470 | opcode 471 | (let ((it (bits-to-int (cl-subseq byte 4)))) 472 | (cl-case it 473 | (0 :CONTINUATION) 474 | (1 :TEXT) 475 | (2 :BINARY) 476 | ((3 4 5 6 7) :NON-CONTROL) 477 | (8 :CLOSE) 478 | (9 :PING) 479 | (10 :PONG) 480 | ((11 12 13 14 15) :CONTROL) 481 | ;; If an unknown opcode is received, the receiving 482 | ;; endpoint MUST _Fail the WebSocket Connection_. 483 | (t (ws-error process 484 | "Web Socket Fail: bad opcode %d" it)))))) 485 | (unless (cl-every #'null rsvs) 486 | ;; MUST be 0 unless an extension is negotiated that defines 487 | ;; meanings for non-zero values. 488 | (ws-error process "Web Socket Fail: non-zero RSV 1 2 or 3")) 489 | ;; Parse mask and payload length 490 | (let ((byte (bits 1))) 491 | (setq mask (car byte) 492 | pl (bits-to-int (cl-subseq byte 1)))) 493 | (unless (eq mask t) 494 | ;; All frames sent from client to server have this bit set to 1. 495 | (ws-error process "Web Socket Fail: client must mask data")) 496 | (cond 497 | ((= pl 126) (setq pl (bits-to-int (bits 2)))) 498 | ((= pl 127) (setq pl (bits-to-int (bits 8))))) 499 | ;; unmask data 500 | (when mask (setq mask-key (cl-subseq pending index (cl-incf index 4)))) 501 | (setq data (concat data 502 | (ws-web-socket-mask 503 | mask-key (cl-subseq pending index (+ index pl))))) 504 | (if fin 505 | ;; wipe the message state and call the handler 506 | (let ((it data)) 507 | (setq data "" active nil pending "" new nil) 508 | ;; close on a close frame, otherwise call the handler 509 | (if (not (eql opcode :CLOSE)) 510 | (funcall handler process it) 511 | (process-send-string process 512 | (unibyte-string (logior (lsh 1 7) 8) 0)))) 513 | ;; add any remaining un-parsed network data to pending 514 | (when (< (+ index pl) (length pending)) 515 | (setq pending (substring pending (+ index pl))))))) 516 | ;; possibly re-parse any pending input 517 | (when (ws-new message) (ws-web-socket-parse-messages message))))) 518 | 519 | (defun ws-web-socket-frame (string &optional opcode) 520 | "Frame STRING for web socket communication." 521 | (let* ((fin 1) ;; set to 0 if not final frame 522 | (len (length string)) 523 | (opcode (cl-ecase (or opcode :TEXT) (:TEXT 1) (:BINARY 2)))) 524 | ;; Does not do any masking which is only required of client communication 525 | (concat 526 | (cond 527 | ((< len 126) (unibyte-string (logior (lsh fin 7) opcode) len)) 528 | ((< len 65536) (unibyte-string (logior (lsh fin 7) opcode) 126 529 | ;; extended 16-bit length 530 | (logand (lsh len -8) 255) 531 | (logand len 255))) 532 | (t (unibyte-string (logior (lsh fin 7) opcode) 127 533 | ;; more extended 64-bit length 534 | (logand (lsh len -56) 255) 535 | (logand (lsh len -48) 255) 536 | (logand (lsh len -40) 255) 537 | (logand (lsh len -32) 255) 538 | (logand (lsh len -24) 255) 539 | (logand (lsh len -16) 255) 540 | (logand (lsh len -8) 255) 541 | (logand len 255)))) 542 | string))) 543 | 544 | 545 | ;;; Content and Transfer encoding support 546 | (defvar ws-compress-cmd "compress" 547 | "Command used for the \"compress\" Content or Transfer coding.") 548 | 549 | (defvar ws-deflate-cmd "zlib-flate -compress" 550 | "Command used for the \"deflate\" Content or Transfer coding.") 551 | 552 | (defvar ws-gzip-cmd "gzip" 553 | "Command used for the \"gzip\" Content or Transfer coding.") 554 | 555 | (defmacro ws-encoding-cmd-to-fn (cmd) 556 | "Return a function which applies CMD to strings." 557 | `(lambda (s) 558 | (with-temp-buffer 559 | (insert s) 560 | (shell-command-on-region (point-min) (point-max) ,cmd nil 'replace) 561 | (buffer-string)))) 562 | 563 | (defun ws-chunk (string) 564 | "Convert STRING to a valid chunk for HTTP chunked Transfer-encoding." 565 | (format "%x\r\n%s\r\n" (string-bytes string) string)) 566 | 567 | 568 | ;;; Convenience functions to write responses 569 | (defun ws-response-header (proc code &rest headers) 570 | "Send the headers for an HTTP response to PROC. 571 | CODE should be an HTTP status code, see `ws-status-codes' for a 572 | list of known codes. 573 | 574 | When \"Content-Encoding\" or \"Transfer-Encoding\" headers are 575 | supplied any subsequent data written to PROC using `ws-send' will 576 | be encoded appropriately including sending the appropriate data 577 | upon the end of transmission for chunked transfer encoding. 578 | 579 | For example with the header `(\"Content-Encoding\" . \"gzip\")', 580 | any data subsequently written to PROC using `ws-send' will be 581 | compressed using the command specified in `ws-gzip-cmd'." 582 | ;; update process to reflect any Content or Transfer encodings 583 | (let ((content (cdr (assoc "Content-Encoding" headers))) 584 | (transfer (cdr (assoc "Transfer-Encoding" headers)))) 585 | (when content 586 | (set-process-plist proc 587 | (append 588 | (list :content-encoding 589 | (cl-ecase (intern content) 590 | ((compress x-compress) (ws-encoding-cmd-to-fn ws-compress-cmd)) 591 | ((deflate x-deflate) (ws-encoding-cmd-to-fn ws-deflate-cmd)) 592 | ((gzip x-gzip) (ws-encoding-cmd-to-fn ws-gzip-cmd)) 593 | (identity #'identity) 594 | ((exi pack200-zip) 595 | (ws-error proc "`%s' Content-encoding not supported." 596 | content)))) 597 | (process-plist proc)))) 598 | (when transfer 599 | (set-process-plist proc 600 | (append 601 | (when (string= transfer "chunked") (list :ender "0\r\n\r\n")) 602 | (list :transfer-encoding 603 | (cl-ecase (intern transfer) 604 | (chunked #'ws-chunk) 605 | ((compress x-compress) (ws-encoding-cmd-to-fn ws-compress-cmd)) 606 | ((deflate x-deflate) (ws-encoding-cmd-to-fn ws-deflate-cmd)) 607 | ((gzip x-gzip) (ws-encoding-cmd-to-fn ws-gzip-cmd)))) 608 | (process-plist proc))))) 609 | (let ((headers 610 | (cons 611 | (format "HTTP/1.1 %d %s" code (cdr (assoc code ws-status-codes))) 612 | (mapcar (lambda (h) (format "%s: %s" (car h) (cdr h))) headers)))) 613 | (setcdr (last headers) (list "" "")) 614 | (process-send-string proc (mapconcat #'identity headers "\r\n")))) 615 | 616 | (defun ws-send (proc string) 617 | "Send STRING to process PROC. 618 | If any Content or Transfer encodings are in use, apply them to 619 | STRING before sending." 620 | (let 621 | ((cc (or (plist-get (process-plist proc) :content-encoding) #'identity)) 622 | (tc (or (plist-get (process-plist proc) :transfer-encoding) #'identity))) 623 | (process-send-string proc (funcall tc (funcall cc string))))) 624 | 625 | (defun ws-send-500 (proc &rest msg-and-args) 626 | "Send 500 \"Internal Server Error\" to PROC with an optional message." 627 | (ws-response-header proc 500 628 | '("Content-type" . "text/plain")) 629 | (process-send-string proc (if msg-and-args 630 | (apply #'format msg-and-args) 631 | "500 Internal Server Error")) 632 | (throw 'close-connection nil)) 633 | 634 | (defun ws-send-404 (proc &rest msg-and-args) 635 | "Send 404 \"Not Found\" to PROC with an optional message." 636 | (ws-response-header proc 404 637 | '("Content-type" . "text/plain")) 638 | (process-send-string proc (if msg-and-args 639 | (apply #'format msg-and-args) 640 | "404 Not Found")) 641 | (throw 'close-connection nil)) 642 | 643 | (defun ws-send-file (proc path &optional mime-type) 644 | "Send PATH to PROC. 645 | Optionally explicitly set MIME-TYPE, otherwise it is guessed by 646 | `mm-default-file-encoding'." 647 | (let ((mime (or mime-type 648 | (mm-default-file-encoding path) 649 | "application/octet-stream"))) 650 | (process-send-string proc 651 | (with-temp-buffer 652 | (insert-file-contents-literally path) 653 | (ws-response-header proc 200 654 | (cons "Content-type" mime) 655 | (cons "Content-length" (- (point-max) (point-min)))) 656 | (buffer-string))))) 657 | 658 | (defun ws-send-directory-list (proc directory &optional match) 659 | "Send a listing of files in DIRECTORY to PROC. 660 | Optional argument MATCH is passed to `directory-files' and may be 661 | used to limit the files sent." 662 | (ws-response-header proc 200 (cons "Content-type" "text/html")) 663 | (process-send-string proc 664 | (concat ""))) 673 | 674 | (defun ws-in-directory-p (parent path) 675 | "Check if PATH is under the PARENT directory. 676 | If so return PATH, if not return nil. Note: the PARENT directory 677 | must be full expanded as with `expand-file-name' and should not 678 | contain e.g., \"~\" for a user home directory." 679 | (if (zerop (length path)) 680 | parent 681 | (let ((expanded (expand-file-name path parent))) 682 | (and (>= (length expanded) (length parent)) 683 | (string= parent (substring expanded 0 (length parent))) 684 | expanded)))) 685 | 686 | (defun ws-with-authentication (handler credentials 687 | &optional realm unauth invalid) 688 | "Return a version of HANDLER protected by CREDENTIALS. 689 | HANDLER should be a function as passed to `ws-start', and 690 | CREDENTIALS should be an alist of elements of the form (USERNAME 691 | . PASSWORD). 692 | 693 | Optional argument REALM sets the realm in the authentication 694 | challenge. Optional arguments UNAUTH and INVALID should be 695 | functions which are called on the request when no authentication 696 | information, or invalid authentication information are provided 697 | respectively." 698 | (let ((handler handler) 699 | (credentials credentials) 700 | (realm realm) 701 | (unauth unauth) 702 | (invalid invalid)) 703 | (lambda (request) 704 | (with-slots (process headers) request 705 | (let ((auth (cddr (assoc :AUTHORIZATION headers)))) 706 | (cond 707 | ;; no authentication information provided 708 | ((not auth) 709 | (if unauth 710 | (funcall unauth request) 711 | (ws-response-header process 401 712 | (cons "WWW-Authenticate" 713 | (format "Basic realm=%S" (or realm "restricted"))) 714 | '("Content-type" . "text/plain")) 715 | (process-send-string process "authentication required"))) 716 | ;; valid authentication information 717 | ((string= (cdr auth) (cdr (assoc (car auth) credentials))) 718 | (funcall handler request)) 719 | ;; invalid authentication information 720 | (t 721 | (if invalid 722 | (funcall invalid request) 723 | (ws-response-header process 403 '("Content-type" . "text/plain")) 724 | (process-send-string process "invalid credentials"))))))))) 725 | 726 | (defun ws-web-socket-handshake (key) 727 | "Perform the handshake defined in RFC6455." 728 | (base64-encode-string (sha1 (concat (ws-trim key) ws-guid) nil nil 'binary))) 729 | 730 | ;;; Enable the old accessors without the `ws-' namespace as obsolete. 731 | ;;; Lets plan to remove these within a year of the date they were 732 | ;;; marked obsolete, so that would be roughly 2021-03-12. 733 | (define-obsolete-function-alias 'active 'ws-active "2020-03-12") 734 | (define-obsolete-function-alias 'body 'ws-body "2020-03-12") 735 | (define-obsolete-function-alias 'boundary 'ws-boundary "2020-03-12") 736 | (define-obsolete-function-alias 'context 'ws-context "2020-03-12") 737 | (define-obsolete-function-alias 'data 'ws-data "2020-03-12") 738 | (define-obsolete-function-alias 'handler 'ws-handler "2020-03-12") 739 | (define-obsolete-function-alias 'handlers 'ws-handlers "2020-03-12") 740 | (define-obsolete-function-alias 'headers 'ws-headers "2020-03-12") 741 | (define-obsolete-function-alias 'index 'ws-index "2020-03-12") 742 | (define-obsolete-function-alias 'new 'ws-new "2020-03-12") 743 | (define-obsolete-function-alias 'pending 'ws-pending "2020-03-12") 744 | (define-obsolete-function-alias 'port 'ws-port "2020-03-12") 745 | (define-obsolete-function-alias 'process 'ws-process "2020-03-12") 746 | (define-obsolete-function-alias 'requests 'ws-requests "2020-03-12") 747 | 748 | (provide 'web-server) 749 | ;;; web-server.el ends here 750 | --------------------------------------------------------------------------------